예제 #1
0
 /// <summary>
 /// Determina  si de acuerdo a los criterios de la especificación de XBRL el arco actual es una relación equivalente al arco a comparar
 /// Un arco es equivalente a otro si relaciona los mismos elementos y si
 /// tiene los mismos atributos no excentos de comparación y
 /// para cada atriburo no excento de comparación hay un atributo equivalente de la misma estructura (s-equal) en el arco a comparar
 /// Atributos: uso y prioridad son excentos y los atributos de los siguientes espacios de nombres:
 /// http://www.w3.org/2000/xmlns/ y http://www.w3.org/1999/xlink son excentos, cualquier otro atributro es no-excento
 /// y los fragmentos de xml de los lados "from" y "to" son identicos entre los 2 arcos
 /// </summary>
 /// <param name="arcoAComparar"></param>
 /// <returns></returns>
 public bool EsRelacionEquivalente(Arco arcoAComparar)
 {
     if (ArcoRol != null && !ArcoRol.Equals(arcoAComparar.ArcoRol))
     {
         return(false);
     }
     return(TieneMismosDestinos(arcoAComparar) && TieneMismosAtributosNoExcentos(arcoAComparar));
 }
예제 #2
0
 /// <summary>
 /// Evalúa si el arco actual está pohibido por el arco enviado como parámetro por los criterios:
 /// El arco a comparar tiene como atributo de uso el valor de "prohibited"
 /// Es el arco actual es una relación equivalente al arco a comparar
 /// La prioridad del arco a comparar es mayor o igual a la prioridad de este arco
 /// </summary>
 /// <param name="arcoAComparar"></param>
 /// <returns></returns>
 public bool EstaProhibidoPor(Arco arcoAComparar)
 {
     if (TiposUso.Prohibido.Valor.Equals(arcoAComparar.Uso))
     {
         if (arcoAComparar.Prioridad >= Prioridad && EsRelacionEquivalente(arcoAComparar))
         {
             return(true);
         }
     }
     return(false);
 }
예제 #3
0
        /// <summary>
        /// Procesa la definición de un arco para que se refleje en la estructura de este arbol.
        /// </summary>
        /// <param name="arco">El arco a procesar</param>
        public void ProcesarArcoRecursivo(Arco arco)
        {
            //Para cada elemento origen
            foreach (ElementoLocalizable elementoDesde in arco.ElementoDesde)
            {
                if (elementoDesde.Destino == null)
                {
                    continue;
                }
                NodoLinkbase         nodoOrigen      = null;
                IList <NodoLinkbase> recorridoOrigen = new List <NodoLinkbase>();
                if (elementoDesde.Destino.Id != null)
                {
                    //empezar a buscar el nodo destino empezando por el raiz considerando el rol
                    nodoOrigen = BuscarNodo(NodoRaiz, elementoDesde.Destino.Id, arco.ArcoRol, recorridoOrigen);
                }
                if (nodoOrigen == null)
                {
                    nodoOrigen = CrearNodo(elementoDesde);
                }


                //Para cada nodo destino
                foreach (ElementoLocalizable elementoHacia in arco.ElementoHacia)
                {
                    NodoLinkbase         nodoDestino      = null;
                    IList <NodoLinkbase> recorridoDestino = new List <NodoLinkbase>();
                    if (elementoHacia.Destino.Id != null)
                    {
                        //empezar a buscar el nodo destino empezando por el raiz considerando el rol
                        nodoDestino = BuscarNodo(NodoRaiz, elementoHacia.Destino.Id, arco.ArcoRol, recorridoDestino);
                    }
                    if (nodoDestino == null)
                    {
                        nodoDestino = CrearNodo(elementoHacia);
                    }

                    AgregarArco(arco, nodoOrigen, nodoDestino);

                    //Verificar si el arco origen no tiene padres, se debe relacionar con el nodo raíz
                    if (!nodoOrigen.TienePadres())
                    {
                        AgregarArco(null, NodoRaiz, nodoOrigen);
                    }

                    //Si el nodo destino tiene como padre al raíz y no participó en un ciclo entonces quitar su relación
                    if (nodoDestino.EsNodoPadre(NodoRaiz) && !recorridoOrigen.Contains(nodoDestino))
                    {
                        QuitarArco(NodoRaiz, nodoDestino);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Crea  una relación entre los nodos origen y destino de acuerdo al arco mandado como parámetro.
        ///
        /// </summary>
        /// <param name="arco">El arco que representa la relación, si el arco es nulo entonces es una relación
        /// no especificada entre 2 nodos, por ejemplo, entre el nodo raíz y el primer hijo</param>
        /// <param name="nodoOrigen">Origen de la relación</param>
        /// <param name="nodoDestino">Destino de la relación</param>
        /// <param name="rol">Rol destino del arco, en caso de que sea importado de otro linkbase rol (caso dimensional)</param>
        private void AgregarArco(Arco arco, NodoLinkbase nodoOrigen, NodoLinkbase nodoDestino, string rol = "")
        {
            //Relación entrante del destino
            var conectorEntrante = new ConectorLinkbase(arco, nodoOrigen);

            nodoDestino.ConectoresEntrantes.Add(conectorEntrante);
            //Relación saliente del origen
            var conectorSaliente = new ConectorLinkbase(arco, nodoDestino);

            if (!String.IsNullOrEmpty(rol))
            {
                conectorSaliente.RolOrigen = rol;
            }
            nodoOrigen.ConectoresSalientes.Add(conectorSaliente);
        }
예제 #5
0
        /// <summary>
        /// Evalúa si este arco tiene los mismos elementos de origen y destino del arco a comparar
        /// </summary>
        /// <param name="arcoAComparar"></param>
        /// <returns></returns>
        private bool TieneMismosDestinos(Arco arcoAComparar)
        {
            if (this == arcoAComparar)
            {
                return(true);
            }

            //Comparar todos los elementos desde
            int elementosIguales = 0;

            foreach (ElementoLocalizable elemento in ElementoDesde)
            {
                //Encontrar el mismo elemento en el arco a comparar
                foreach (ElementoLocalizable elementoAComparar in arcoAComparar.ElementoDesde)
                {
                    if (elemento.Destino == elementoAComparar.Destino)
                    {
                        elementosIguales++;
                        break;
                    }
                }
            }
            if (elementosIguales != ElementoDesde.Count)
            {
                return(false);
            }
            //Comparar todos los elementos hacia
            elementosIguales = 0;
            foreach (ElementoLocalizable elemento in ElementoHacia)
            {
                //Encontrar el mismo elemento en el arco a comparar
                foreach (ElementoLocalizable elementoAComparar in arcoAComparar.ElementoHacia)
                {
                    if (elemento.Destino == elementoAComparar.Destino)
                    {
                        elementosIguales++;
                        break;
                    }
                }
            }
            if (elementosIguales != ElementoDesde.Count)
            {
                return(false);
            }
            return(true);
        }
예제 #6
0
 /// <summary>
 /// Evalúa si este arco es reemplazado por el arco a comparar enviado como parámetro
 /// El arco a comparar tiene como atributo de uso el valor de "optional"
 /// El arco actual es una relación equivalente al arco a comparar
 /// La prioridad del arco a comparar es mayor o igual a la prioridad de este arco
 /// </summary>
 /// <param name="arcoAComparar">Arco a verificar si reemplaza al actual</param>
 /// <returns></returns>
 public bool EsReemplazadoPor(Arco arcoAComparar)
 {
     return(arcoAComparar.Prioridad >= Prioridad && EsRelacionEquivalente(arcoAComparar));
 }
예제 #7
0
        /// <summary>
        /// Verifica que los atributos no excentos de un arco sean iguales a los atributos no excentos del otro arco:
        /// Atributos excentos:
        /// uso y prioridad y los atributos cuyo namespace sea:
        /// http://www.w3.org/2000/xmlns/ y http://www.w3.org/1999/xlink
        /// </summary>
        /// <param name="arcoAComparar"></param>
        /// <returns></returns>
        private bool TieneMismosAtributosNoExcentos(Arco arcoAComparar)
        {
            //Extraer atriburos no excenteos de ambos - se omite el atriburo de orden con el fin de compararlo manualmente
            IList <XmlAttribute> atributosNoExcentos         = new List <XmlAttribute>();
            IList <XmlAttribute> atributosNoExcentosComparar = new List <XmlAttribute>();

            foreach (XmlAttribute attr in ElementoXML.Attributes)
            {
                if (!(EtiquetasXBRLConstantes.UseAttribute.Equals(attr.LocalName) || EtiquetasXBRLConstantes.PriorityAttribute.Equals(attr.LocalName) ||
                      EtiquetasXBRLConstantes.OrderAttribute.Equals(attr.LocalName) ||
                      EspacioNombresConstantes.XLinkNamespace.Equals(attr.NamespaceURI) ||
                      EspacioNombresConstantes.NamespaceAttriburosExcentos.Equals(attr.NamespaceURI)))
                {
                    atributosNoExcentos.Add(attr);
                }
            }
            foreach (XmlAttribute attr in arcoAComparar.ElementoXML.Attributes)
            {
                if (!(EtiquetasXBRLConstantes.UseAttribute.Equals(attr.LocalName) || EtiquetasXBRLConstantes.PriorityAttribute.Equals(attr.LocalName) ||
                      EtiquetasXBRLConstantes.OrderAttribute.Equals(attr.LocalName) ||
                      EspacioNombresConstantes.XLinkNamespace.Equals(attr.NamespaceURI) ||
                      EspacioNombresConstantes.NamespaceAttriburosExcentos.Equals(attr.NamespaceURI)))
                {
                    atributosNoExcentosComparar.Add(attr);
                }
            }

            if (atributosNoExcentos.Count != atributosNoExcentosComparar.Count)
            {
                return(false);
            }
            //buscar si hacen match los atributos
            foreach (XmlAttribute attr in atributosNoExcentos)
            {
                string valorNormalizado = XmlUtil.NormalizarValorNumerico(attr);
                bool   attrIgual        = false;
                foreach (XmlAttribute attrComparar in atributosNoExcentosComparar)
                {
                    if (attr.NamespaceURI.Equals(attrComparar.NamespaceURI) && attr.LocalName.Equals(attrComparar.LocalName))
                    {
                        string valorNormalizadoAcomparar = XmlUtil.NormalizarValorNumerico(attrComparar);
                        if (!valorNormalizado.Equals(valorNormalizadoAcomparar))
                        {
                            return(false);
                        }
                        else
                        {
                            attrIgual = true;
                            break;
                        }
                    }
                }
                if (!attrIgual)
                {
                    return(false);
                }
            }
            //finalmente comparar el orden

            return(Orden == arcoAComparar.Orden);
        }
예제 #8
0
        /// <summary>
        /// Importa los arcos que han sido recuperado de otro role y los agrega a las relaciones del árbol únicamente a partir
        /// del conector inicial enviado como parámetro.
        /// Todos los arcos generan nuevos nodos para no interferir con las relaciones ya existentes
        /// </summary>
        /// <param name="conector">Conector inicial</param>
        /// <param name="arcosConsecutivos">Arcos a crear</param>
        public void ImportarArcos(ConectorLinkbase conector, IDictionary <Arco, String> arcosConsecutivos)
        {
            var nodosCreados = new List <NodoLinkbase>();

            nodosCreados.Add(conector.NodoSiguiente);
            //Si el nodo siguiente del conector no está en el inventario, agregar
            if (!IndicePorId.Values.Contains(conector.NodoSiguiente))
            {
                if (IndicePorId.ContainsKey(conector.NodoSiguiente.Elemento.Id))
                {
                    String id = "E" + Guid.NewGuid().ToString();
                    IndicePorId.Add(conector.NodoSiguiente.Elemento.Id + "_" + id, conector.NodoSiguiente);
                }
            }
            var arcosPendientes = arcosConsecutivos.ToDictionary(keyVal => keyVal.Key, keyVal => keyVal.Value);

            while (arcosPendientes.Count > 0)
            {
                Arco arcoUsado = null;
                //buscar en los arcos pendientes el enlace entre el nodo siguiente y el arco
                foreach (var arcoActual in arcosPendientes)
                {
                    //para este arco, buscar que nodo le corresponde
                    foreach (var elementoDesde in arcoActual.Key.ElementoDesde)
                    {
                        var nodoOrigenArco = nodosCreados.FirstOrDefault(x => x.Elemento == elementoDesde.Destino);
                        if (nodoOrigenArco != null)
                        {
                            //Nodo localizado, crear arco
                            foreach (var elementoHacia in arcoActual.Key.ElementoHacia)
                            {
                                NodoLinkbase nodoSiguiente = new NodoLinkbase();
                                nodosCreados.Add(nodoSiguiente);
                                nodoSiguiente.Elemento            = elementoHacia.Destino;
                                nodoSiguiente.ConectoresEntrantes = new List <ConectorLinkbase>();
                                nodoSiguiente.ConectoresSalientes = new List <ConectorLinkbase>();
                                //Si el nodo creado corresponde a un concepto entonces agregarlo al índice con su ID, de lo contrario, generar uno temporal
                                if (elementoHacia.Destino is ConceptTuple || elementoHacia.Destino is ConceptItem)
                                {
                                    if (IndicePorId.ContainsKey(elementoHacia.Destino.Id))
                                    {
                                        String id = "E" + Guid.NewGuid().ToString();
                                        IndicePorId.Add(elementoHacia.Destino.Id + "_" + id, nodoSiguiente);
                                    }
                                    else
                                    {
                                        IndicePorId.Add(elementoHacia.Destino.Id, nodoSiguiente);
                                    }
                                }
                                else
                                {
                                    String id = "E" + Guid.NewGuid().ToString();
                                    nodoSiguiente.Elemento.Id = id;
                                    IndicePorId.Add(id, nodoSiguiente);
                                }
                                AgregarArco(arcoActual.Key, nodoOrigenArco, nodoSiguiente, arcoActual.Value);
                                arcoUsado = arcoActual.Key;
                            }
                        }
                    }
                    if (arcoUsado != null)
                    {
                        break;
                    }
                }
                if (arcoUsado != null)
                {
                    arcosPendientes.Remove(arcoUsado);
                }
            }
            //Verificar los nodos que no tienen elementos entrantes, apuntarlos al raíz
            VerificarElementosHuerfanos();
        }
예제 #9
0
 /// <summary>
 /// Constructor completo
 /// </summary>
 /// <param name="_arco">Arco por el cuál se crea el conector</param>
 /// <param name="_nodoSiguente">Nodo al que apunta el contector</param>
 public ConectorLinkbase(Arco _arco, NodoLinkbase _nodoSiguente)
 {
     Arco          = _arco;
     NodoSiguiente = _nodoSiguente;
 }