/// <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>
        /// 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);
        }