/// <summary>
        /// Build from a REST query and a bean retrival manager
        /// </summary>
        /// <param name="dataQuery"></param>
        /// <param name="retrievalManager"></param>
        /// <exception cref="SdmxSemmanticException"></exception>
        public DataQueryImpl(IRestDataQuery dataQuery, ISdmxObjectRetrievalManager retrievalManager)
        {
            this._lastUpdated = dataQuery.UpdatedAfter;
            this._dataQueryDetail = dataQuery.QueryDetail ?? DataQueryDetail.GetFromEnum(DataQueryDetailEnumType.Full);

            base.FirstNObservations = dataQuery.FirstNObservations;
            base.LastNObservations = dataQuery.LastNObsertations;
            if (ObjectUtil.ValidString(dataQuery.DimensionAtObservation))
            {
                this.DimensionAtObservation = dataQuery.DimensionAtObservation;
            }

            base.Dataflow = retrievalManager.GetMaintainableObject<IDataflowObject>(dataQuery.FlowRef.MaintainableReference);
            if (base.Dataflow == null)
            {
                throw new SdmxNoResultsException("Data Flow could not be found for query : " + dataQuery.FlowRef);
            }

            base.DataStructure =
                retrievalManager.GetMaintainableObject<IDataStructureObject>(base.Dataflow.DataStructureRef.MaintainableReference);
            if (base.DataStructure == null)
            {
                throw new SdmxNoResultsException("DSD could not be found for query : " + base.Dataflow.DataStructureRef);
            }

            ISet<IDataProvider> dataProviders = new HashSet<IDataProvider>();
            if (dataQuery.ProviderRef != null)
            {
                ISet<IDataProviderScheme> dataProviderSchemes =
                    retrievalManager.GetMaintainableObjects<IDataProviderScheme>(dataQuery.ProviderRef.MaintainableReference);
                foreach (IDataProviderScheme currentDpScheme in dataProviderSchemes)
                {
                    foreach (IDataProvider dataProvider in currentDpScheme.Items)
                    {
                        if (dataProvider.Id.Equals(dataQuery.ProviderRef.ChildReference.Id))
                        {
                            dataProviders.Add(dataProvider);
                        }
                    }
                }
            }
            ISet<IDataQuerySelection> selections = new HashSet<IDataQuerySelection>();
            if (dataQuery.QueryList.Count > 0)
            {
                int i = 0;
                foreach (IDimension dimension in base.DataStructure.GetDimensions(SdmxStructureEnumType.Dimension, SdmxStructureEnumType.MeasureDimension).OrderBy(dimension => dimension.Position))
                {
                    if (dataQuery.QueryList.Count <= i)
                    {
                        throw new SdmxSemmanticException(
                            "Not enough key values in query, expecting "
                            + base.DataStructure.GetDimensions(SdmxStructureEnumType.Dimension, SdmxStructureEnumType.MeasureDimension).Count + " got "
                            + dataQuery.QueryList.Count);
                    }
                    ISet<string> queriesForDimension = dataQuery.QueryList[i];
                    if (queriesForDimension != null && queriesForDimension.Count > 0)
                    {
                        IDataQuerySelection selectionsForDimension =
                            new DataQueryDimensionSelectionImpl(
                                dimension.Id,
                                new HashSet<string>(queriesForDimension));
                        selections.Add(selectionsForDimension);
                    }
                    i++;
                }
            }

            if (ObjectUtil.ValidCollection(selections) || dataQuery.StartPeriod != null || dataQuery.EndPeriod != null)
            {
                _dataQuerySelectionGroups.Add(
                    new DataQuerySelectionGroupImpl(selections, dataQuery.StartPeriod, dataQuery.EndPeriod));
            }
            ValidateQuery();
        }
 /// <summary>
 /// Adds components to the component map.
 /// </summary>
 /// <param name="retrievalManager">
 /// The retrieval manager
 /// </param>
 /// <param name="crossRef">
 /// The cross reference object
 /// </param>
 /// <param name="componentMap">
 /// The components map
 /// </param>
 private void AddComponenents(ISdmxObjectRetrievalManager retrievalManager, ICrossReference crossRef, IDictionary<String, IComponent> componentMap)
 {
     switch (crossRef.TargetReference.EnumType)
     {
         case SdmxStructureEnumType.ProvisionAgreement:
             IProvisionAgreementObject prov = retrievalManager.GetMaintainableObject<IProvisionAgreementObject>(crossRef);
             if (prov == null)
             {
                 prov = _beanRetrievalManager.GetMaintainableObject<IProvisionAgreementObject>(crossRef);
                 if (prov == null)
                     throw new CrossReferenceException(crossRef);
             }
             crossRef = prov.StructureUseage;  //Drop through to the next switch statement
             break;
         case SdmxStructureEnumType.Dataflow:
             IDataflowObject flow = retrievalManager.GetMaintainableObject<IDataflowObject>(crossRef);
             if (flow == null)
             {
                 flow = _beanRetrievalManager.GetMaintainableObject<IDataflowObject>(crossRef);
                 if (flow == null)
                     throw new CrossReferenceException(crossRef);
             }
             crossRef = flow.DataStructureRef;  //Drop through to the next switch statement
             break;
         case SdmxStructureEnumType.Dsd:
             IDataStructureObject dsd = retrievalManager.GetMaintainableObject<IDataStructureObject>(crossRef);
             if (dsd == null)
             {
                 dsd = _beanRetrievalManager.GetMaintainableObject<IDataStructureObject>(crossRef);
                 if (dsd == null)
                     throw new CrossReferenceException(crossRef);
             }
             foreach (IComponent currentComponent in dsd.Components)
                 componentMap.Add(currentComponent.Id, currentComponent);
             break;
     }
 }
        /// <summary>
        /// Processes the dataWhere element to get the Provisionn Agreeement reference and retrieve the respective artefact bean.
        /// If the provision agreement cannot be found it throws an exception.
        /// </summary>
        /// <param name="dataWhere">
        /// The data where.
        /// </param>
        /// <param name="structureRetrievalManager">
        /// The structure retrieval manager.
        /// </param>
        /// <returns>
        /// The provision agreement object.
        /// </returns>
        private IProvisionAgreementObject GetProvisionAgreement(DataParametersAndType dataWhere, ISdmxObjectRetrievalManager structureRetrievalManager)
        {
            IProvisionAgreementObject provisionAgreement = null;

            if (dataWhere.ProvisionAgreement != null && dataWhere.ProvisionAgreement.Count > 0)
            {
                var refBaseType = dataWhere.ProvisionAgreement[0].GetTypedRef<ProvisionAgreementRefType>();
                string praAgency = refBaseType.agencyID;
                string praId = refBaseType.id;
                string praVersion = null;
                if (refBaseType.version != null)
                    praVersion = refBaseType.version;
                IMaintainableRefObject praRef = new MaintainableRefObjectImpl(praAgency, praId, praVersion);
                provisionAgreement = structureRetrievalManager.GetMaintainableObject<IProvisionAgreementObject>(praRef);
                if (provisionAgreement == null)
                {
                    throw new SdmxNoResultsException("Provision Agreement not found: " + praRef);
                }
            }
            return provisionAgreement;
        }
        /// <summary>
        /// Processes the dataWhere element to get the DSD reference and retrieve the respective DSD.
        /// It throws an exception if the DSD cannot be retrieved.
        /// </summary>
        /// <param name="dataWhere">
        /// The data where.
        /// </param>
        /// <param name="structureRetrievalManager">
        /// The structure retrieval manager.
        /// </param>
        /// <param name="dataFlow">
        /// The data flow.
        /// </param>
        /// <returns>
        /// The data structure object.
        /// </returns>
        private IDataStructureObject GetDataWhereDataStrucuture(DataParametersAndType dataWhere,
                                            ISdmxObjectRetrievalManager structureRetrievalManager,
                                            IDataflowObject dataFlow)
        {
            IDataStructureObject dataStructure = null;

            if (dataWhere.DataStructure != null && dataWhere.DataStructure.Count > 0)
            {
                var refBaseType = dataWhere.DataStructure[0].GetTypedRef<DataStructureRefType>();
                string dataStructureAgency = refBaseType.agencyID;
                string dataStructureId = refBaseType.id;
                string dataStructureVersion = null;
                if (refBaseType.version != null)
                    dataStructureVersion = refBaseType.version;

                IMaintainableRefObject dsdRef = new MaintainableRefObjectImpl(dataStructureAgency, dataStructureId, dataStructureVersion);
                dataStructure = structureRetrievalManager.GetMaintainableObject<IDataStructureObject>(dsdRef);
                if (dataStructure == null)
                {
                    throw new SdmxNoResultsException("DSD not found: " + dsdRef);
                }
            }
            else
            {
                IMaintainableRefObject dsdRef = dataFlow.DataStructureRef.MaintainableReference;
                dataStructure = structureRetrievalManager.GetMaintainableObject<IDataStructureObject>(dsdRef);
                if (dataStructure == null)
                {
                    throw new SdmxNoResultsException("Data Structure not found: " + dsdRef);
                }
            }
            return dataStructure;
        }
        /// <summary>
        /// Processes the dataWhere element to get the dataflow reference and retrieve the respective dataflow.
        /// It throws an exception if the dataflow retrieved is null
        /// </summary>
        /// <param name="dataWhere">
        /// The data where.
        /// </param>
        /// <param name="structureRetrievalManager">
        /// The structure retrieval manager.
        /// </param>
        /// <returns>
        /// The data flow object.
        /// </returns>
        private IDataflowObject GetDataWhereDataFlow(DataParametersAndType dataWhere, ISdmxObjectRetrievalManager structureRetrievalManager)
        {
            IDataflowObject dataFlow = null;
            if (dataWhere.Dataflow != null && dataWhere.Dataflow.Count > 0)
            {
                var dataflowRefType = dataWhere.Dataflow[0].GetTypedRef<DataflowRefType>();
                string dataFlowAgency = dataflowRefType.agencyID;
                string dataFlowId = dataflowRefType.id;
                string dataFlowVersion = null; // null if not specified so as to get the latest

                if (dataflowRefType.version != null)
                {
                    dataFlowVersion = dataflowRefType.version;
                }

                IMaintainableRefObject flowRef = new MaintainableRefObjectImpl(dataFlowAgency, dataFlowId, dataFlowVersion);
                dataFlow = structureRetrievalManager.GetMaintainableObject<IDataflowObject>(flowRef);
                if (dataFlow == null)
                {
                    throw new SdmxNoResultsException("Dataflow not found: " + flowRef);
                }
            }
            else
            {
                throw new ArgumentException("Can not create DataQuery, Dataflow is required");
            }
            return dataFlow;
        }
        /// <summary>
        /// Builds a data provider bean from DataProviderReferenceType from XML 
        /// </summary>
        /// <param name="dataProviderRef">
        /// The data provider reference.
        /// </param>
        /// <param name="structureRetrievalManager">
        /// The structure retrieval manager.
        /// </param>
        /// <returns>
        /// The data provider.
        /// </returns>
        private IDataProvider ProcessDataProviderType(DataProviderReferenceType dataProviderRef, ISdmxObjectRetrievalManager structureRetrievalManager)
        {
            var dataProviderRefType = dataProviderRef.GetTypedRef<DataProviderRefType>();
            string agencyId = dataProviderRefType.agencyID;
            string id = dataProviderRefType.maintainableParentID;
            string version = dataProviderRefType.maintainableParentVersion;

            IMaintainableRefObject orgSchemeRef = new MaintainableRefObjectImpl(agencyId, id, version);
            IDataProviderScheme dataProviderScheme = structureRetrievalManager.GetMaintainableObject<IDataProviderScheme>(orgSchemeRef);
            foreach (IDataProvider dp in dataProviderScheme.Items)
            {
                if (dp.Id.Equals(dataProviderRefType.id))
                {
                    return dp;
                }
            }
            return null;
        }
            /// <summary>
            /// Builds a data query from <paramref name="dataWhereType"/>
            /// </summary>
            /// <param name="dataWhereType">
            /// The data Where Type.
            /// </param>
            /// <param name="structureRetrievalManager">
            /// The structure Retrieval Manager.
            /// </param>
            /// <returns>
            /// The <see cref="IDataQuery"/>.
            /// </returns>
            public IDataQuery BuildDataQuery(
                DataWhereType dataWhereType, ISdmxObjectRetrievalManager structureRetrievalManager)
            {
                if (structureRetrievalManager == null)
                {
                    throw new ArgumentNullException("structureRetrievalManager");
                }

                this.ProcessDataWhere(dataWhereType);
                this.ProcessAnd(dataWhereType.And);

                IMaintainableRefObject flowRef = new MaintainableRefObjectImpl(
                    this._agencyId, this._dataflowId, this._version);
                IDataflowObject dataflow = structureRetrievalManager.GetMaintainableObject<IDataflowObject>(flowRef);
                if (dataflow == null)
                {
                    throw new SdmxNoResultsException("Dataflow not found: " + flowRef);
                }

                IMaintainableRefObject dsdRef = dataflow.DataStructureRef.MaintainableReference;
                IDataStructureObject dataStructureBean = structureRetrievalManager.GetMaintainableObject<IDataStructureObject>(dsdRef);
                if (dataStructureBean == null)
                {
                    throw new SdmxNoResultsException("Data Structure not found: " + dsdRef);
                }

                // TODO check if DSD is v2.0 compatible
                if (!dataStructureBean.IsCompatible(SdmxSchema.GetFromEnum(SdmxSchemaEnumType.VersionTwo)))
                {
                    throw new SdmxSemmanticException("DataStructure used for this dataflow is not SDMX v2.0 compatible.");
                }

                var convertedDataQuerySelectionGroups = ConvertConceptIdToComponentId(this._dataQuerySelectionGroups, dataStructureBean);

                // FUNC Data Provider
                return new DataQueryImpl(
                    dataStructureBean,
                    null,
                    null,
                    this._defaultLimit /* was null TODO */,
                    true,
                    null,
                    dataflow,
                    null,
                    convertedDataQuerySelectionGroups);
            }