/// <summary>
        /// Busca uno o mas hechos que correspondan con los filtros enviados como parámetro.
        /// Si un filtro es nulo entonces no se considera para filtrar al hecho
        /// </summary>
        /// <param name="idConcepto">Identificador del concepto buscad</param>
        /// <param name="entidad">Entidad a considerar del concepto</param>
        /// <param name="unidad">Unidad buscada del hecho</param>
        /// <param name="fechaInicio">Fecha posible de inicio</param>
        /// <param name="fechaFin">Fecha posible de fin</param>
        /// <param name="valoresDimensiones">Valores dimensionales a considerar</param>
        /// <param name="considerarDimensiones">Indica si se deben de considerar o no las dimensiones para buscar un hecho</param>
        /// <returns>Lista de hechos que corresponden con la búsqueda</returns>
        public IList <HechoDto> BuscarHechos(string idConcepto, EntidadDto entidad, UnidadDto unidad, DateTime fechaInicio, DateTime fechaFin, IList <DimensionInfoDto> valoresDimensiones,
                                             bool considerarDimensiones = true)
        {
            IList <HechoDto> hechosResultado = new List <HechoDto>();

            foreach (var listaHechos in HechosPorIdConcepto.Where(x => x.Key.Equals(idConcepto)))
            {
                foreach (var idHecho in listaHechos.Value)
                {
                    var hecho       = HechosPorId[idHecho];
                    var contexto    = ContextosPorId.ContainsKey(hecho.IdContexto) ? ContextosPorId[hecho.IdContexto] : null;
                    var unidadHecho = !String.IsNullOrEmpty(hecho.IdUnidad) && UnidadesPorId.ContainsKey(hecho.IdUnidad) ? UnidadesPorId[hecho.IdUnidad] : null;
                    if (contexto != null)
                    {
                        if (entidad != null)
                        {
                            //Revisar entidad
                            if (!String.IsNullOrEmpty(entidad.EsquemaId) && !entidad.EsquemaId.Equals(contexto.Entidad.EsquemaId))
                            {
                                continue;
                            }
                            if (!String.IsNullOrEmpty(entidad.Id) && !entidad.Id.Equals(contexto.Entidad.Id))
                            {
                                continue;
                            }
                        }
                        //Verificar unidad
                        if (unidad != null && unidadHecho != null && !unidadHecho.EsEquivalente(unidad))
                        {
                            continue;
                        }
                        //Verificar fechas
                        if (contexto.Periodo.Tipo == Period.Instante)
                        {
                            if (!contexto.Periodo.FechaInstante.Equals(fechaFin))
                            {
                                continue;
                            }
                        }
                        else if (contexto.Periodo.Tipo == Period.Duracion)
                        {
                            if (!contexto.Periodo.FechaFin.Equals(fechaFin) || !contexto.Periodo.FechaInicio.Equals(fechaInicio))
                            {
                                continue;
                            }
                        }
                        //Verificar dimensiones
                        if (considerarDimensiones && !contexto.SonDimensionesEquivalentes(valoresDimensiones))
                        {
                            continue;
                        }
                        hechosResultado.Add(hecho);
                    }
                }
            }
            return(hechosResultado);
        }
        /// <summary>
        /// Libera los recursos asociados al documento de instancia
        /// </summary>
        public void Cerrar()
        {
            this.Taxonomia = null;

            if (ContextosPorFecha != null)
            {
                ContextosPorFecha.Clear();
                ContextosPorFecha = null;
            }

            if (EntidadesPorId != null)
            {
                EntidadesPorId.Clear();
                EntidadesPorId = null;
            }

            if (Errores != null)
            {
                Errores.Clear();
                Errores = null;
            }

            if (HechosPorIdContexto != null)
            {
                HechosPorIdContexto.Clear();
                HechosPorIdContexto = null;
            }

            if (HechosPorIdConcepto != null)
            {
                HechosPorIdConcepto.Clear();
                HechosPorIdConcepto = null;
            }

            if (HechosPorIdUnidad != null)
            {
                HechosPorIdUnidad.Clear();
                HechosPorIdUnidad = null;
            }

            if (UnidadesPorId != null)
            {
                UnidadesPorId.Clear();
                UnidadesPorId = null;
            }

            if (ContextosPorId != null)
            {
                foreach (var ctx in ContextosPorId.Values)
                {
                    if (ctx.Entidad != null)
                    {
                        if (ctx.Entidad.ValoresDimension != null)
                        {
                            ctx.Entidad.ValoresDimension.Clear();
                            ctx.Entidad.ValoresDimension = null;
                        }
                        ctx.Entidad = null;
                    }
                    if (ctx.Periodo != null)
                    {
                        ctx.Periodo = null;
                    }
                    if (ctx.ValoresDimension != null)
                    {
                        ctx.ValoresDimension.Clear();
                        ctx.ValoresDimension = null;
                    }
                }
                ContextosPorId.Clear();
                ContextosPorId = null;
            }

            if (HechosPorId != null)
            {
                foreach (var hecho in HechosPorId.Values)
                {
                    LiberarHecho(hecho);
                }
                HechosPorId.Clear();
            }

            if (DtsDocumentoInstancia != null)
            {
                DtsDocumentoInstancia.Clear();
                DtsDocumentoInstancia = null;
            }

            if (estructurasDocumentoInstanciaPorRol != null)
            {
                foreach (var est in estructurasDocumentoInstanciaPorRol.Values)
                {
                    est.Clear();
                }
                estructurasDocumentoInstanciaPorRol.Clear();
            }
        }
        /// <summary>
        /// Importa los datos de un hecho de otro documento de instancia.
        /// Busca unidad o contexto que sea equivalente, de otra forma crea unidades y contextos asociados
        /// </summary>
        /// <param name="hechoImportar">Hecho a importar</param>
        /// <param name="instancia">Documento de instancia orgien del hecho</param>
        /// <returns>ID del hecho importado en le documento de instancia</returns>
        public String ImportarHecho(HechoDto hechoImportar, DocumentoInstanciaXbrlDto instancia)
        {
            String nuevoId = null;

            if (this.Taxonomia.ConceptosPorId.ContainsKey(hechoImportar.IdConcepto))
            {
                nuevoId = "I" + Guid.NewGuid().ToString();
                String idContexto = null;
                String idUnidad   = null;

                if (hechoImportar.IdUnidad != null)
                {
                    UnidadDto unidadOrigen      = instancia.UnidadesPorId[hechoImportar.IdUnidad];
                    var       uniadesNuevoHecho = BuscarUnidades(unidadOrigen.Tipo, Unit.Medida == unidadOrigen.Tipo ?unidadOrigen.Medidas :unidadOrigen.MedidasNumerador, unidadOrigen.MedidasDenominador);
                    if (uniadesNuevoHecho != null && uniadesNuevoHecho.Count > 0)
                    {
                        idUnidad = uniadesNuevoHecho[0].Id;
                    }
                    else
                    {
                        var unidadDestino = new UnidadDto()
                        {
                            Id                 = "UI" + Guid.NewGuid().ToString(),
                            Tipo               = unidadOrigen.Tipo,
                            Medidas            = unidadOrigen.Medidas,
                            MedidasNumerador   = unidadOrigen.MedidasNumerador,
                            MedidasDenominador = unidadOrigen.MedidasDenominador
                        };
                        UnidadesPorId.Add(unidadDestino.Id, unidadDestino);
                        idUnidad = unidadDestino.Id;
                    }
                }

                if (hechoImportar.IdContexto != null)
                {
                    ContextoDto contextoOrigen = instancia.ContextosPorId[hechoImportar.IdContexto];
                    var         valoresDim     = new List <DimensionInfoDto>();
                    if (contextoOrigen.Entidad.ValoresDimension != null)
                    {
                        valoresDim.AddRange(contextoOrigen.Entidad.ValoresDimension);
                    }
                    if (contextoOrigen.ValoresDimension != null)
                    {
                        valoresDim.AddRange(contextoOrigen.ValoresDimension);
                    }

                    var contextos = BuscarContexto(contextoOrigen.Entidad.EsquemaId + ":" + contextoOrigen.Entidad.Id, contextoOrigen.Periodo.Tipo,
                                                   contextoOrigen.Periodo.Tipo == Period.Instante? contextoOrigen.Periodo.FechaInstante:contextoOrigen.Periodo.FechaInicio,
                                                   contextoOrigen.Periodo.Tipo == Period.Instante? contextoOrigen.Periodo.FechaInstante:contextoOrigen.Periodo.FechaFin,
                                                   valoresDim
                                                   );
                    if (contextos != null && contextos.Count > 0)
                    {
                        idContexto = contextos[0].Id;
                        //LogUtil.Info("{contextoOrigen.Entidad.Id: [" + contextoOrigen.Entidad.Id + "], contextoDocumento.Entidad.Id:[" + contextos[0].Entidad.Id + "]}");
                    }
                    else
                    {
                        var contextoDestino = new ContextoDto()
                        {
                            Entidad = new EntidadDto()
                            {
                                ContieneInformacionDimensional = contextoOrigen.Entidad.ContieneInformacionDimensional,
                                EsquemaId = contextoOrigen.Entidad.EsquemaId,
                                Id        = contextoOrigen.Entidad.Id
                            },
                            ContieneInformacionDimensional = contextoOrigen.ContieneInformacionDimensional,
                            Periodo = new PeriodoDto()
                            {
                                Tipo          = contextoOrigen.Periodo.Tipo,
                                FechaInicio   = contextoOrigen.Periodo.FechaInicio,
                                FechaFin      = contextoOrigen.Periodo.FechaFin,
                                FechaInstante = contextoOrigen.Periodo.FechaInstante
                            },
                            ValoresDimension = contextoOrigen.ValoresDimension,
                            Id = "CI" + Guid.NewGuid().ToString()
                        };
                        ContextosPorId[contextoDestino.Id] = contextoDestino;
                        idContexto = contextoDestino.Id;
                    }
                }

                var hechoNuevo = CrearHecho(hechoImportar.IdConcepto, idUnidad, idContexto, nuevoId);
                hechoNuevo.Valor         = hechoImportar.Valor;
                hechoNuevo.ValorNumerico = hechoImportar.ValorNumerico;


                HechosPorId[nuevoId] = hechoNuevo;
                if (!HechosPorIdConcepto.ContainsKey(hechoNuevo.IdConcepto))
                {
                    HechosPorIdConcepto[hechoNuevo.IdConcepto] = new List <String>();
                }
                HechosPorIdConcepto[hechoNuevo.IdConcepto].Add(nuevoId);
            }

            return(nuevoId);
        }
        /// <summary>
        /// Crea un nuevo hecho para el concepto enviado, asociándolo al contexto y unidad enviados como parámetro, el
        /// contexto y la unidad son opcionales, también asigna el ID de hecho enviado como parámetro.
        /// Agrega el hecho a los distintos índices del documento
        /// </summary>
        /// <param name="idConcepto">Identificador del concepto para el hecho a crear</param>
        /// <param name="idUnidad">Identificador opcional de la unidad del concepto, obligatorio para datos numéricos</param>
        /// <param name="idContexto">Contexto del hecho, no necesario para tuplas</param>
        /// <param name="idHecho">Identificador opcional del hecho</param>
        /// <returns>El hecho creado</returns>
        public HechoDto CrearHecho(string idConcepto, string idUnidad, string idContexto, string idHecho)
        {
            HechoDto hechoNuevo = null;

            if (String.IsNullOrEmpty(idConcepto) || Taxonomia == null || !Taxonomia.ConceptosPorId.ContainsKey(idConcepto))
            {
                return(null);
            }

            var concepto    = Taxonomia.ConceptosPorId[idConcepto];
            var EsAbstracto = concepto.EsAbstracto != null ? concepto.EsAbstracto.Value : false;

            if (!EsAbstracto)
            {
                if ((concepto.Tipo == Concept.Item && !ContextosPorId.ContainsKey(idContexto)) ||
                    (concepto.EsTipoDatoNumerico && !UnidadesPorId.ContainsKey(idUnidad)))
                {
                    return(null);
                }
                if (idHecho != null && HechosPorId.ContainsKey(idHecho))
                {
                    return(null);
                }
                hechoNuevo = new HechoDto()
                {
                    IdConcepto            = idConcepto,
                    NombreConcepto        = concepto.Nombre,
                    EspacioNombres        = concepto.EspacioNombres,
                    Tipo                  = concepto.Tipo,
                    Id                    = idHecho,
                    CambioValorComparador = false,
                };

                if (concepto.Tipo == Concept.Item)
                {
                    hechoNuevo.EsTupla      = false;
                    hechoNuevo.TipoDato     = concepto.TipoDato;
                    hechoNuevo.TipoDatoXbrl = concepto.TipoDatoXbrl;
                    if (concepto.EsTipoDatoNumerico)
                    {
                        hechoNuevo.EsNumerico = true;
                        hechoNuevo.IdContexto = idContexto;
                        hechoNuevo.Valor      = null;
                        hechoNuevo.IdUnidad   = idUnidad;
                        hechoNuevo.Decimales  = "0";
                    }
                    else
                    {
                        hechoNuevo.NoEsNumerico = true;
                        hechoNuevo.IdContexto   = idContexto;
                        hechoNuevo.Valor        = null;
                    }
                }
                else if (concepto.Tipo == Concept.Tuple)
                {
                    hechoNuevo.EsTupla      = true;
                    hechoNuevo.NoEsNumerico = true;
                }
            }
            return(hechoNuevo);
        }