private void ImprimirNodo(int nivel, NodoLinkbase nodo, List <NodoLinkbase> impresos) { if (nivel > 50) { return; } if (impresos.Count(nod => nod == nodo) > 1) { return; } //Imprimir este nodo en el nivel int espacios = nivel * 5; for (int i = 0; i < espacios; i++) { Debug.Write(" "); } Debug.WriteLine(nodo.Elemento.Id); impresos.Add(nodo); foreach (ConectorLinkbase conn in nodo.ConectoresSalientes) { ImprimirNodo(nivel + 1, conn.NodoSiguiente, impresos); } }
/// <summary> /// Recorre el árbol en busca de la definición de hipercubos y para cada declaración /// recorre el subárbol del hipercubo buscando ciclos dirigidos /// </summary> /// <param name="nodo">Nodo actualemnte verificado</param> /// <returns>True si existe algún ciclo dirigido de hipercubo en el nodo</returns> private bool ValidarCiclosDirigidosEnHipercubos(NodoLinkbase nodo, IList <ElementoXBRL> nodosVisitadosPrincipal) { bool existeCiclo = false; foreach (var conector in nodo.ConectoresSalientes) { if (conector.Arco != null && (conector.Arco.ArcoRol.Equals(ArcoDefinicion.HasHypercubeAllRole) || conector.Arco.ArcoRol.Equals(ArcoDefinicion.HasHypercubeNotAllRole))) { //Se encontró la declaración de un cubo, validar ciclos IList <ConceptItem> nodosVisitados = new List <ConceptItem>(); if (ExisteCicloEnHipercubo(nodosVisitados, nodo, conector)) { existeCiclo = true; break; } } if (nodosVisitadosPrincipal.Contains(nodo.Elemento)) { return(false); } nodosVisitadosPrincipal.Add(nodo.Elemento); if (ValidarCiclosDirigidosEnHipercubos(conector.NodoSiguiente, nodosVisitadosPrincipal)) { existeCiclo = true; break; } } nodosVisitadosPrincipal.Remove(nodo.Elemento); return(existeCiclo); }
/// <summary> /// Recorre el arbol de relaciones dimensionales en busca de elemento primarios, los agrega a la lista de elementos primarios /// </summary> /// <param name="nodoActual"></param> private void LlenarElementosPrimarios(NodoLinkbase nodoActual) { foreach (var conector in nodoActual.ConectoresSalientes.Where(x => x.Arco.ArcoRol.Equals(ArcoDefinicion.DomainMemberRole))) { if (!_elementosPrimarios.Contains(conector.NodoSiguiente.Elemento)) { _elementosPrimarios.Add(conector.NodoSiguiente.Elemento as ConceptItem); LlenarElementosPrimarios(conector.NodoSiguiente); } } }
private void ImprimirNodo(int nivel, NodoLinkbase nodo) { //Imprimir este nodo en el nivel int espacios = nivel * 5; for (int i = 0; i < espacios; i++) { Debug.Write(" "); } Debug.WriteLine(nodo.Elemento.Id); foreach (ConectorLinkbase conn in nodo.ConectoresSalientes) { ImprimirNodo(nivel + 1, conn.NodoSiguiente); } }
/// <summary> /// Colecta los miembros válidos de dominio de dimensiones /// </summary> /// <param name="dimension">Declaración de la dimensión</param> /// <param name="nodoActual"> </param> /// <param name="tax"> </param> private void LlenarDominioDeDimension(Dimension dimension, NodoLinkbase nodoActual, ITaxonomiaXBRL tax) { IList <string> arcoRolesBuscados = new List <string>() { ArcoDefinicion.DimensionDomainRole, ArcoDefinicion.DomainMemberRole }; foreach (var conectorSiguiente in nodoActual.ConectoresSalientes.Where(x => x.Arco != null && arcoRolesBuscados.Contains(x.Arco.ArcoRol))) { //considerar el atributo usable if (!((conectorSiguiente.Arco as ArcoDefinicion).Usable != null && !(conectorSiguiente.Arco as ArcoDefinicion).Usable.Value)) { if (!dimension.MiembrosDominio.Contains(conectorSiguiente.NodoSiguiente.Elemento)) { dimension.MiembrosDominio.Add(conectorSiguiente.NodoSiguiente.Elemento as ConceptItem); } } else { if (!dimension.MiembrosDominioNoUsables.Contains(conectorSiguiente.NodoSiguiente.Elemento)) { dimension.MiembrosDominioNoUsables.Add(conectorSiguiente.NodoSiguiente.Elemento as ConceptItem); } } LlenarDominioDeDimension(dimension, conectorSiguiente.NodoSiguiente, tax); } if (!dimension.Explicita) { //Localizar el schema element de la dimensión if (dimension.ConceptoDimension.ReferenciaDimensionTipificada != null) { foreach (var esquema in tax.ArchivosEsquema.Where(x => x.Key.Equals(dimension.ConceptoDimension.ReferenciaDimensionTipificada.UbicacionArchivo))) { foreach (XmlSchemaElement unElemento in esquema.Value.Elements.Values) { if (unElemento.Id != null && unElemento.Id.Equals(dimension.ConceptoDimension.ReferenciaDimensionTipificada.Identificador)) { dimension.ConceptoDimension.ElementoDimensionTipificada = unElemento; break; } } } } } }
/// <summary> /// Realiza el recorrido de un hipercubo validando si ya se ha visitado algún nodo realizando un recorrido ordenado /// </summary> /// <param name="nodosVisitados"></param> /// <param name="nodo"></param> /// <param name="conectorOrigen"></param> private bool ExisteCicloEnHipercubo(IList <ConceptItem> nodosVisitados, NodoLinkbase nodo, ConectorLinkbase conectorOrigen) { if (nodosVisitados.Contains(nodo.Elemento)) { //Error return(true); } nodosVisitados.Add(nodo.Elemento as ConceptItem); foreach (var conectorActual in nodo.ConectoresSalientes.Where(x => x.Arco != null && ArcoDefinicion.RolesArcosDimensionalesConsecutivos.ContainsKey(x.Arco.ArcoRol))) { if (ExisteCicloEnHipercubo(nodosVisitados, conectorActual.NodoSiguiente, conectorOrigen)) { return(true); } } nodosVisitados.Remove(nodo.Elemento as ConceptItem); return(false); }
/// <summary> /// Constructor básico, se necesita un nodo con la declaración del elemento primario para inicial el hipercubo /// </summary> /// <param name="nodoOrigen"></param> public Hipercubo(NodoLinkbase nodoOrigen, ConectorLinkbase conectorInicial, RoleType rol, IDictionary <ConceptDimensionItem, ConceptItem> listaDimensionesDefault, ITaxonomiaXBRL tax) { ListaDimensiones = new List <Dimension>(); Rol = rol; DeclaracionElementoPrimario = nodoOrigen; //Elementos primarios _elementosPrimarios.Add(nodoOrigen.Elemento as ConceptItem); LlenarElementosPrimarios(nodoOrigen); //Determinar el tipo de elemento en el contexto donde aparece la información dimensional del hipercubo ElementoContexto = (conectorInicial.Arco as ArcoDefinicion).ElementoContexto; //Atributo cerrado Cerrado = (conectorInicial.Arco as ArcoDefinicion).Closed != null ? (conectorInicial.Arco as ArcoDefinicion).Closed.Value : false; ArcRoleDeclaracion = conectorInicial.Arco.ArcoRol; ElementoHipercubo = conectorInicial.NodoSiguiente; //Dimensiones foreach (var conectoresDimension in ElementoHipercubo.ConectoresSalientes.Where(x => x.Arco.ArcoRol.Equals(ArcoDefinicion.HypercubeDimensionRole))) { var dimDec = new Dimension(); dimDec.ConceptoDimension = conectoresDimension.NodoSiguiente.Elemento as ConceptDimensionItem; dimDec.Explicita = dimDec.ConceptoDimension.ReferenciaDimensionTipificada == null; ListaDimensiones.Add(dimDec); foreach (var dimDefault in listaDimensionesDefault.Where(x => x.Key == conectoresDimension.NodoSiguiente.Elemento)) { if (!_dimensionDefaults.ContainsKey(dimDefault.Key)) { _dimensionDefaults.Add(dimDefault.Key, dimDefault.Value); dimDec.MiembroDefault = dimDefault.Value; } } //Llenar dominio de dimensión LlenarDominioDeDimension(dimDec, conectoresDimension.NodoSiguiente, tax); //Quitar del dominio a los elementos no usables que pudieran quedar repetidos foreach (var noUsable in dimDec.MiembrosDominioNoUsables) { dimDec.MiembrosDominio.Remove(noUsable); } } }
/// <summary> /// Recorre el árbol en busca de la definición de hipercubos y para cada hipercubo validar que sus primary items no sean /// parte de los miembros válidos de las dimensiones del hipercubo /// </summary> /// <param name="nodo">Nodo actualmente verificado</param> /// <param name="elementoXbrls"> </param> private void ValidarPrimaryItemEnMiembrosValidos(NodoLinkbase nodo, IList <ElementoXBRL> nodosVisitados) { if (nodosVisitados.Contains(nodo.Elemento)) { return; } nodosVisitados.Add(nodo.Elemento); foreach (var conector in nodo.ConectoresSalientes) { if (conector.Arco != null && (conector.Arco.ArcoRol.Equals(ArcoDefinicion.HasHypercubeAllRole) || conector.Arco.ArcoRol.Equals(ArcoDefinicion.HasHypercubeNotAllRole))) { //Se encontró la declaración de un cubo, obtener sus elementos primarios en forma de lista IList <ConceptItem> elementosPrimarios = new List <ConceptItem>(); ObtenerListaElementosPrimarios(elementosPrimarios, nodo); VerificarElementoPrimarioEnMiembro(elementosPrimarios, conector.NodoSiguiente, conector); } ValidarPrimaryItemEnMiembrosValidos(conector.NodoSiguiente, nodosVisitados); } nodosVisitados.Remove(nodo.Elemento); }
/// <summary> /// Colecta una lista de elementos partiendo del nodo origen que estén relacionados por arcos domain-member /// </summary> /// <param name="nodo">Nodo origen</param> private void ObtenerListaElementosPrimarios(IList <ConceptItem> elementosPrimarios, NodoLinkbase nodo) { if (elementosPrimarios.Contains(nodo.Elemento)) { return; } elementosPrimarios.Add(nodo.Elemento as ConceptItem); foreach (var conector in nodo.ConectoresSalientes.Where(x => x.Arco != null && x.Arco.ArcoRol.Equals(ArcoDefinicion.DomainMemberRole))) { ObtenerListaElementosPrimarios(elementosPrimarios, conector.NodoSiguiente); } }
/// <summary> /// Verifica si los elementos primarios existen también como miembros válidos de las dimensiones de un cubo, /// notifica un error en caso de encontrar coincidencias /// </summary> /// <param name="elementosPrimarios">Lista de elementos primarios</param> /// <param name="nodo">Nodo origen</param> /// <param name="conectorOrigenHipercubo">Conector origen del hipercubo</param> /// <param name="miembroUsable">Indica si el miembro de la dimensión es usable de acuerdo a su arco antecesor</param> private void VerificarElementoPrimarioEnMiembro(IList <ConceptItem> elementosPrimarios, NodoLinkbase nodo, ConectorLinkbase conectorOrigenHipercubo, bool miembroUsable = true) { if (miembroUsable && elementosPrimarios.Contains(nodo.Elemento)) { ManejadorErrores.ManejarError(CodigosErrorXBRL.PrimaryItemPolymorphismError, null, "2.5.3.1.1.3 Se encontró un conjunto de arcos que relacionan elementos que definen un hipercubo donde fue detectado un ciclo: Hipercubo: " + conectorOrigenHipercubo.NodoSiguiente.Elemento.Id, XmlSeverityType.Error); } foreach (var conector in nodo.ConectoresSalientes.Where(x => x.Arco != null && (x.Arco.ArcoRol.Equals(ArcoDefinicion.HypercubeDimensionRole) || x.Arco.ArcoRol.Equals(ArcoDefinicion.DimensionDomainRole) || x.Arco.ArcoRol.Equals(ArcoDefinicion.DomainMemberRole)))) { VerificarElementoPrimarioEnMiembro(elementosPrimarios, conector.NodoSiguiente, conectorOrigenHipercubo, (conector.Arco as ArcoDefinicion).Usable != null? (conector.Arco as ArcoDefinicion).Usable.Value:true); } }
public void TestCargaTaxonomia() { TaxonomiaXBRL taxonomiaXBRL = new TaxonomiaXBRL(); IManejadorErroresXBRL manejadorErrores = new ManejadorErroresCargaTaxonomia(); taxonomiaXBRL.ManejadorErrores = manejadorErrores; //Boolean correcto = taxonomiaXBRL.ProcesarDefinicionDeEsquemaRef("C:\\workspaces\\memoria_xbrl\\Ejercicio Práctico\\taxonomia1-2012-07-01-core.xsd"); //Boolean correcto = taxonomiaXBRL.ProcesarDefinicionDeEsquemaRef("C:\\dotNet\\AbaxXBRL_1\\AbaxXBRL\\XBRL-CONF-CR5-2012-01-24\\Common\\100-schema\\155-TypeExtension-Valid.xsd"); taxonomiaXBRL.ProcesarDefinicionDeEsquema(@"C:\taxonomy\mx-ifrs-2014-12-05\full_ifrs_mc_mx_ics_entry_point_2014-12-05.xsd"); taxonomiaXBRL.CrearArbolDeRelaciones(); XbrlViewerService serv = new XbrlViewerService(); var taxDt = serv.CrearTaxonomiaAPartirDeDefinicionXbrl(taxonomiaXBRL); var docServ = new DocumentoInstanciaService(); docServ.PerteneceConceptoAHipercuboEnRol("ifrs-full_ProfitLoss", taxDt, "http://bmv.com.mx/role/ifrs/ias_1_2014-03-05_role-610000"); foreach (RoleType tipoRol in taxonomiaXBRL.RolesTaxonomia.Values) { ArbolLinkbase arbolPresentation = taxonomiaXBRL.ConjuntoArbolesLinkbase[tipoRol.RolURI.ToString()][LinkbasePresentacion.RolePresentacionLinkbaseRef]; NodoLinkbase nodo = arbolPresentation.NodoRaiz; ImprimirNodo(0, nodo); Debug.WriteLine("________________________________________"); if (tipoRol.Linkbases.ContainsKey(LinkbaseReferencia.RoleReferenceLinkbaseRef)) { LinkbaseReferencia linkbase = (LinkbaseReferencia)tipoRol.Linkbases[LinkbaseReferencia.RoleReferenceLinkbaseRef]; foreach (Arco arco in linkbase.Arcos) { foreach (ElementoLocalizable elementoDesde in arco.ElementoDesde) { Concept conceptoDesde = (Concept)((Localizador)elementoDesde).Destino; foreach (ElementoLocalizable elementoHacia in arco.ElementoHacia) { Referencia referencia = (Referencia)elementoHacia.Destino; Debug.WriteLine(conceptoDesde.Elemento.Id + " Referencias: "); foreach (ReferenciaParte refPart in referencia.PartesReferencia) { Debug.WriteLine("\tReferencia:" + refPart.NombreLocal + " : " + refPart.Valor); } } } } } Debug.WriteLine("________________________________________"); if (tipoRol.Linkbases.ContainsKey(LinkbaseCalculo.RoleCalculoLinkbaseRef)) { LinkbaseCalculo linkbase = (LinkbaseCalculo)tipoRol.Linkbases[LinkbaseCalculo.RoleCalculoLinkbaseRef]; //Escribir los elementos que no tienen padre Debug.WriteLine(tipoRol.Id); IDictionary <string, string> impresos = new Dictionary <string, string>(); foreach (ArcoCalculo arco in linkbase.Arcos) { foreach (ElementoLocalizable elementoDesde in arco.ElementoDesde) { Concept conceptoDesde = (Concept)elementoDesde.Destino; if (!tienePadre(conceptoDesde, linkbase.Arcos)) { if (!impresos.ContainsKey(conceptoDesde.Elemento.Id)) { Debug.WriteLine(conceptoDesde.Elemento.Id); imprimirHijosCalculo(1, conceptoDesde.Elemento.Id, linkbase.Arcos, (LinkbaseCalculo)tipoRol.Linkbases[LinkbaseCalculo.RoleCalculoLinkbaseRef]); impresos[conceptoDesde.Elemento.Id] = conceptoDesde.Elemento.Id; } } } } } } Assert.IsTrue(true); }