public ProvisionAgreementObjectBaseCore(
				IProvisionAgreementObject provisionAgreement,
				IDataflowObjectBase dataflowSuperBean,
				IDataProvider dataProviderBean) : base(provisionAgreement) {
			this._provisionAgreement = provisionAgreement;
			this._dataflowSuper = dataflowSuperBean;
			this._dataProvider = dataProviderBean;
			try {
				Validate();
			} catch (ValidationException e) {
				throw new ValidationException(e,
						"Error creating provision agreement super bean : "
								+ provisionAgreement.Urn);
			}
		}
        /// <summary>
        /// The update references.
        /// </summary>
        /// <param name="maintianable">
        /// The maintianable.
        /// </param>
        /// <param name="updateReferences">
        /// The update references.
        /// </param>
        /// <param name="newVersionNumber">
        /// The new version number.
        /// </param>
        /// <returns>
        /// The <see cref="IProvisionAgreementObject"/>.
        /// </returns>
        public IProvisionAgreementObject UpdateReferences(
            IProvisionAgreementObject maintianable,
            IDictionary<IStructureReference, IStructureReference> updateReferences,
            string newVersionNumber)
        {
            IProvisionAgreementMutableObject provision = maintianable.MutableInstance;
            provision.Version = newVersionNumber;

            IStructureReference newTarget = updateReferences[provision.DataproviderRef];
            if (newTarget != null)
            {
                provision.DataproviderRef = newTarget;
            }
            newTarget = updateReferences[provision.StructureUsage];
            if (newTarget != null)
            {
                provision.StructureUsage = newTarget;
            }
            return provision.ImmutableInstance;
        }
		private bool IsMatch(IProvisionAgreementObject provision,
				IMaintainableObject bean) {
			/* foreach */
			foreach (ICrossReference currentRef  in  provision.CrossReferences) {
				if (currentRef.IsMatch(bean)) {
					return true;
				}
			}
			return false;
		}
	    public ComplexDataQueryImpl(string datasetId, 
								TextSearch datasetIdOperator, 
								ISet<IDataProvider> dataProviders, 
								IDataStructureObject dataStructure, 
								IDataflowObject dataFlow,
								IProvisionAgreementObject provisionAgreement,  
								IList<ITimeRange> lastUpdatedDate, 
								int? maxObs, 
								int? defaultLimit, 
								bool orderAsc, 
								ObservationAction obsAction, 
								string dimensionAtObservation,
								bool hasExplicitMeasures, 
								DataQueryDetail queryDetail, 
								ICollection<IComplexDataQuerySelectionGroup> complexDataQuerySelectionGroup)
        {

		    this._datasetId = datasetId;

		    if (datasetIdOperator != null)
			    this._datasetIdOperator = datasetIdOperator;
		    else
			    this._datasetIdOperator = TextSearch.GetFromEnum(TextSearchEnumType.Equal);
		
            if (dataProviders != null) 
            {
			    this._dataProviders = new HashSet<IDataProvider>(dataProviders);
		    }

		    base.DataStructure = dataStructure;
		    base.Dataflow = dataFlow;
		    this._provisionAgreement = provisionAgreement;

		    if(lastUpdatedDate != null) 
            {
			    this._lastUpdatedDate = new List<ITimeRange>(lastUpdatedDate);
		    }

		    if (orderAsc) 
			    base.FirstNObservations = maxObs;
		    else 
			    base.LastNObservations = maxObs;

		    this._defaultLimit = defaultLimit;

		    if (obsAction!=null)
			    this._obsAction = obsAction;
		    else 
			    this._obsAction = ObservationAction.GetFromEnum(ObservationActionEnumType.Active);

		    this.DimensionAtObservation = dimensionAtObservation;

		    if (dimensionAtObservation != null)
            {
			    //the values: 'AllDimensions' and 'TIME_PERIOD' are valid values.
			    if (dimensionAtObservation.Equals(_allDimensions) || dimensionAtObservation.Equals(DimensionAtObservationEnumType.Time.ToString()))
				    this.DimensionAtObservation = dimensionAtObservation;
			    else //check if the value is a dimension Value
				    CheckDimensionExistence(dimensionAtObservation, dataStructure);
		    }
            else
            {
			    this.DimensionAtObservation = GetDimensionAtObservationLevel(dataStructure);
		    }

		    this._hasExplicitMeasures = hasExplicitMeasures;

		    if (queryDetail != null)
			    this._queryDetail = queryDetail;
		    else
			    this._queryDetail = DataQueryDetail.GetFromEnum(DataQueryDetailEnumType.Full);

		    if (complexDataQuerySelectionGroup != null) 
            {
			    foreach (IComplexDataQuerySelectionGroup cdqsg in complexDataQuerySelectionGroup) 
                {
				    if (cdqsg != null) 
                    {
					    this._complexDataQuerySelectionGroups.Add(cdqsg);
				    }
			    }
		    }

		    //perform validation 	
		    ValidateQuery();
		    ValidateProvisionAgreement();
	    }
	    public ComplexDataQueryImpl(string datasetId, TextSearch datasetIdOperator, 
                                    ISet<IDataProvider> dataProviders, 
			                        IDataStructureObject dataStructure, IDataflowObject dataFlow,
			                        IProvisionAgreementObject provisionAgreement, 
                                    IList<ITimeRange> lastUpdatedDate,  
			                        int? firstNObs, int? lastNObs, int? defaultLimit, 
                                    ObservationAction obsAction, string dimensionAtObservation,
			                        bool hasExplicitMeasures, DataQueryDetail queryDetail, 
                                    ISet<IComplexDataQuerySelection> complexSelections, 
			                        DateTime dateFrom, OrderedOperator dateFromOperator, 
                                    DateTime dateTo,  OrderedOperator dateToOperator,
                                    ISet<IComplexComponentValue> primaryMeasureValues)
        {
		    this._datasetId = datasetId;
		    if (datasetIdOperator != null)
			    this._datasetIdOperator = datasetIdOperator;
		    else
			    this._datasetIdOperator = TextSearch.GetFromEnum(TextSearchEnumType.Equal);

		    this._dataProviders = dataProviders;
		    base.DataStructure = dataStructure;
		    base.Dataflow = dataFlow;
		    this._provisionAgreement = provisionAgreement;
		    this._lastUpdatedDate = lastUpdatedDate;
		    base.FirstNObservations = firstNObs;
		    base.LastNObservations = lastNObs;
		    this._defaultLimit = defaultLimit;

		    if (obsAction != null)
			    this._obsAction = obsAction;
		    else 
			    this._obsAction = ObservationAction.GetFromEnum(ObservationActionEnumType.Active);

		    this.DimensionAtObservation = dimensionAtObservation;
		    if (dimensionAtObservation != null)
            {
			    //the values: 'AllDimensions' and 'TIME_PERIOD' are valid values.
			    if (dimensionAtObservation.Equals(_allDimensions) || dimensionAtObservation.Equals(DimensionAtObservationEnumType.Time.ToString()))
				    this.DimensionAtObservation = dimensionAtObservation;
			    else//check if the value is a dimension Value
				    CheckDimensionExistence(dimensionAtObservation, dataStructure);
		    }
            else
            {
			    this.DimensionAtObservation = GetDimensionAtObservationLevel(dataStructure);
		    }
		
		    this._hasExplicitMeasures = hasExplicitMeasures;
		    if (queryDetail != null)
			    this._queryDetail = queryDetail;
		    else
			    this._queryDetail = DataQueryDetail.GetFromEnum(DataQueryDetailEnumType.Full);

		    if(ObjectUtil.ValidCollection(complexSelections) || dateFrom != null || dateTo != null) 
            {
			    ISdmxDate sdmxDateFrom = null;
			    if(dateFrom != null) 
                {
				    sdmxDateFrom = new SdmxDateCore(dateFrom, TimeFormatEnumType.Date);
			    }
			    ISdmxDate sdmxDateTo = null;
			    if(dateFrom != null) {
				    sdmxDateTo = new SdmxDateCore(dateTo, TimeFormatEnumType.Date);
			    }
			    this._complexDataQuerySelectionGroups.Add(new ComplexDataQuerySelectionGroupImpl(complexSelections, sdmxDateFrom, dateFromOperator, sdmxDateTo,  dateToOperator, primaryMeasureValues));
		    }

		    //perform validation 	
		    ValidateQuery();
		    ValidateProvisionAgreement();
	    }
        /// <summary>
        /// The process response.
        /// </summary>
        /// <param name="returnType">
        /// The return type.
        /// </param>
        /// <param name="provisionAgreement">
        /// The provision agreement.
        /// </param>
        private void ProcessResponse(
            SubmitProvisioningResponseType returnType, IProvisionAgreementObject provisionAgreement)
        {
            var statusType = new ProvisioningStatusType();
            returnType.ProvisioningStatus.Add(statusType);
            var statusMessage = new StatusMessageType();
            statusType.StatusMessage = statusMessage;
            this.AddStatus(statusMessage, null);

            var provRefType = new ProvisionAgreementRefType();
            statusType.ProvisionAgreementRef = provRefType;

            if (ObjectUtil.ValidString(provisionAgreement.Urn))
            {
                provRefType.URN = provisionAgreement.Urn;
            }

            if (provisionAgreement.DataproviderRef != null)
            {
                ICrossReference crossRef = provisionAgreement.DataproviderRef;
                IMaintainableRefObject maintRef = crossRef.MaintainableReference;
                string value = maintRef.AgencyId;
                if (!string.IsNullOrWhiteSpace(value))
                {
                    provRefType.OrganisationSchemeAgencyID = maintRef.AgencyId;
                }

                string value1 = maintRef.MaintainableId;
                if (!string.IsNullOrWhiteSpace(value1))
                {
                    provRefType.OrganisationSchemeID = maintRef.MaintainableId;
                }

                string value2 = crossRef.ChildReference.Id;
                if (crossRef.ChildReference != null && !string.IsNullOrWhiteSpace(value2))
                {
                    provRefType.DataProviderID = crossRef.ChildReference.Id;
                }

                string value3 = maintRef.Version;
                if (!string.IsNullOrWhiteSpace(value3))
                {
                    provRefType.DataProviderVersion = maintRef.Version;
                }
            }

            if (provisionAgreement.StructureUseage != null)
            {
                ICrossReference structUseageCrossRef = provisionAgreement.StructureUseage;
                IMaintainableRefObject maintRef0 = structUseageCrossRef.MaintainableReference;
                if (structUseageCrossRef.TargetReference.EnumType == SdmxStructureEnumType.Dataflow)
                {
                    string value = maintRef0.AgencyId;
                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        provRefType.DataflowAgencyID = maintRef0.AgencyId;
                    }

                    string value1 = maintRef0.MaintainableId;
                    if (!string.IsNullOrWhiteSpace(value1))
                    {
                        provRefType.DataflowID = maintRef0.MaintainableId;
                    }

                    string value2 = maintRef0.Version;
                    if (!string.IsNullOrWhiteSpace(value2))
                    {
                        provRefType.DataflowVersion = maintRef0.Version;
                    }
                }
            }
        }
        /// <summary>
        ///     Determines the current data structure.
        /// </summary>
        /// <exception cref="SdmxNoResultsException">
        ///     Could not read dataset, the data set references dataflow '+errorString+' which could not be resolved
        ///     or
        ///     Could not read dataset, the data set references provision '+errorString+' which could not be resolved
        ///     or
        ///     Could not read dataset, the data set references dataflow '+errorString+' which could not be resolved
        ///     or
        ///     Can not read dataset, the data set references the DSD ' + errorString + ' which could not be resolved
        ///     or
        ///     Can not read dataset, the data set does no reference any data structures, and there was no default data structure
        ///     definition provided
        /// </exception>
        /// <exception cref="SdmxNotImplementedException">Can not write dataset for structure of type:  + sRef</exception>
        private void DetermineCurrentDataStructure()
        {
            // 1. Set the current DSD to null before trying to resolve it
            this._currentDsd = null;
            this._currentDataflow = null;
            this._currentProvisionAgreement = null;

            IDatasetStructureReference datasetStructureReference = null;
            if (this._datasetHeader != null)
            {
                datasetStructureReference = this._datasetHeader.DataStructureReference;
                if (datasetStructureReference == null && this._headerObject != null && this._headerObject.Structures.Count == 1)
                {
                    datasetStructureReference = this._headerObject.Structures[0];
                }
            }

            if (datasetStructureReference != null)
            {
                var structureReference = datasetStructureReference.StructureReference;

                string errorString = structureReference.MaintainableReference.ToString();

                // Provision, Flow, DSD or MSD
                switch (structureReference.TargetReference.EnumType)
                {
                    case SdmxStructureEnumType.Dsd:
                        if (this._defaultDsd != null && structureReference.IsMatch(this._defaultDsd))
                        {
                            this.SetCurrentDsd(this._defaultDsd);
                        }
                        else if (this.ObjectRetrieval != null)
                        {
                            this.SetCurrentDsd(structureReference.MaintainableReference);
                        }

                        break;
                    case SdmxStructureEnumType.Dataflow:
                        if (this.ObjectRetrieval != null)
                        {
                            this._currentDataflow = this.ObjectRetrieval.GetMaintainableObject<IDataflowObject>(structureReference.MaintainableReference);
                            if (this._currentDataflow == null)
                            {
                                throw new SdmxNoResultsException("Could not read dataset, the data set references dataflow '" + errorString + "' which could not be resolved");
                            }

                            this.SetCurrentDsd(this._currentDataflow.DataStructureRef.MaintainableReference);
                        }
                        else
                        {
                            // Use the "header" values 
                            this.SetCurrentDsd(this._defaultDsd);
                            this._currentDataflow = this._defaultDataflow;
                        }

                        break;
                    case SdmxStructureEnumType.ProvisionAgreement:
                        if (this.ObjectRetrieval != null)
                        {
                            this._currentProvisionAgreement = this.ObjectRetrieval.GetMaintainableObject<IProvisionAgreementObject>(structureReference.MaintainableReference);
                            if (this._currentProvisionAgreement == null)
                            {
                                throw new SdmxNoResultsException("Could not read dataset, the data set references provision '" + errorString + "' which could not be resolved");
                            }

                            this._currentDataflow = this.ObjectRetrieval.GetMaintainableObject<IDataflowObject>(this._currentProvisionAgreement.StructureUseage.MaintainableReference);
                            if (this._currentDataflow == null)
                            {
                                throw new SdmxNoResultsException("Could not read dataset, the data set references dataflow '" + errorString + "' which could not be resolved");
                            }

                            this.SetCurrentDsd(this._currentDataflow.DataStructureRef.MaintainableReference);
                        }

                        break;
                    default:
                        throw new SdmxNotImplementedException("Can not write dataset for structure of type: " + structureReference);
                }

                if (this._currentDsd == null)
                {
                    throw new SdmxNoResultsException("Can not read dataset, the data set references the DSD '" + errorString + "' which could not be resolved");
                }
            }
            else if (this._defaultDsd == null)
            {
                throw new SdmxNoResultsException("Can not read dataset, the data set does no reference any data structures, and there was no default data structure definition provided");
            }
            else
            {
                if (this._defaultDataflow != null)
                {
                    this.SetCurrentDataflow(this._defaultDataflow);
                }
                else
                {
                    this.SetCurrentDsd(this._defaultDsd);
                }
            }
        }
        /// <summary>
        /// Build <see cref="ProvisionAgreementType"/> from <paramref name="buildFrom"/>.
        /// </summary>
        /// <param name="buildFrom">
        /// The build from.
        /// </param>
        /// <returns>
        /// The <see cref="ProvisionAgreementType"/> from <paramref name="buildFrom"/> .
        /// </returns>
        public ProvisionAgreementType Build(IProvisionAgreementObject buildFrom)
        {
            var builtObj = new ProvisionAgreementType();

            string value = buildFrom.Id;
            if (!string.IsNullOrWhiteSpace(value))
            {
                builtObj.id = buildFrom.Id;
            }

            if (buildFrom.Uri != null)
            {
                builtObj.uri = buildFrom.Uri;
            }
            else if (buildFrom.StructureUrl != null)
            {
                builtObj.uri = buildFrom.StructureUrl;
            }
            else if (buildFrom.ServiceUrl != null)
            {
                builtObj.uri = buildFrom.StructureUrl;
            }

            if (ObjectUtil.ValidString(buildFrom.Urn))
            {
                builtObj.urn = buildFrom.Urn;
            }

            IList<ITextTypeWrapper> names = buildFrom.Names;
            if (ObjectUtil.ValidCollection(names))
            {
                builtObj.Name = this.GetTextType(names);
            }

            IList<ITextTypeWrapper> descriptions = buildFrom.Descriptions;
            if (ObjectUtil.ValidCollection(descriptions))
            {
                builtObj.Description = this.GetTextType(descriptions);
            }

            if (this.HasAnnotations(buildFrom))
            {
                builtObj.Annotations = this.GetAnnotationsType(buildFrom);
            }

            if (buildFrom.StructureUseage != null)
            {
                if (buildFrom.StructureUseage.TargetReference.EnumType == SdmxStructureEnumType.Dataflow)
                {
                    DataflowRefType dataflowRef = builtObj.DataflowRef = new DataflowRefType();
                    this.PopulateDataflowRef(buildFrom.StructureUseage, dataflowRef);
                }
                else if (buildFrom.StructureUseage.TargetReference.EnumType == SdmxStructureEnumType.MetadataFlow)
                {
                    MetadataflowRefType metadataflowRef = builtObj.MetadataflowRef = new MetadataflowRefType();
                    this.PopulateMetadataflowRef(buildFrom.StructureUseage, metadataflowRef);
                }
            }

            if (buildFrom.DataproviderRef != null)
            {
                DataProviderRefType dataProviderRef = builtObj.DataProviderRef = new DataProviderRefType();
                this.PopulateDataproviderRef(buildFrom.DataproviderRef, dataProviderRef);
            }

            return builtObj;
        }
        /// <summary>
        ///   Returns a set of structures that are directly referenced from this provision
        /// </summary>
        /// <param name="provision"> - the provision to resolve the references for </param>
        /// <param name="structRetrievalManager"> - must not be null as this will be used to resolve the references </param>
        /// <returns> a set of structures that are directly referenced from this provision </returns>
        public virtual ISet<IIdentifiableObject> ResolveReferences(
            IProvisionAgreementObject provision, IIdentifiableRetrievalManager structRetrievalManager)
        {
            if (structRetrievalManager == null)
            {
                throw new ArgumentNullException("structRetrievalManager", "StructureRetrievalManager can not be null");
            }

            ISet<IIdentifiableObject> returnSet = new HashSet<IIdentifiableObject>();
            if (provision.StructureUseage != null)
            {
                IIdentifiableObject structureUseage =
                    structRetrievalManager.GetIdentifiableObject(provision.StructureUseage);

                if (structureUseage == null)
                {
                    throw new CrossReferenceException(
                        provision.StructureUseage);
                }

                returnSet.Add(structureUseage);
            }

            if (provision.DataproviderRef != null)
            {
                IIdentifiableObject dataProvider = structRetrievalManager.GetIdentifiableObject(provision.DataproviderRef);
                if (dataProvider == null)
                    throw new CrossReferenceException(provision.DataproviderRef);

                returnSet.Add(dataProvider);
            }

            return returnSet;
        }
        /// <summary>
        /// Returns a set of structures that are directly referenced from this provision
        /// </summary>
        /// <param name="provision">
        /// - the provision to resolve the references for 
        /// </param>
        /// <param name="structRetrievalManager">
        /// - must not be null as this will be used to resolve the references 
        /// </param>
        /// <returns>
        ///  a set of structures that are directly referenced from this provision
        /// </returns>
        public virtual ISet<IIdentifiableObject> ResolveReferences(
            IProvisionAgreementObject provision, ISdmxRetrievalManager structRetrievalManager)
        {
            if (structRetrievalManager == null)
            {
                throw new ArgumentException("StructureRetrievalManager can not be null");
            }

            this._structureRetrievalManager = structRetrievalManager;

            ISet<IIdentifiableObject> returnSet = new HashSet<IIdentifiableObject>();
            if (provision.StructureUseage != null)
            {
                IMaintainableObject structureUseage = structRetrievalManager.GetMaintainable(provision.StructureUseage);

                if (structureUseage == null)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        provision.StructureUseage.TargetReference.GetType(), 
                        provision.StructureUseage);
                }

                returnSet.Add(structureUseage);
            }

            if (provision.DataproviderRef != null)
            {
                IDataProviderScheme orgScheme =
                    structRetrievalManager.GetDataProviderSchemeBean(provision.DataproviderRef.MaintainableReference);
                if (orgScheme == null)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProviderScheme).ToString(), 
                        provision.DataproviderRef.MaintainableReference);
                }

                var dataProviders = orgScheme.Items;
                if (!ObjectUtil.ValidCollection(dataProviders))
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProvider).ToString(), 
                        provision.DataproviderRef);
                }

                bool found = false;

                /* foreach */
                foreach (IDataProvider dataProvider in dataProviders)
                {
                    if (dataProvider.Id.Equals(provision.DataproviderRef.ChildReference.Id))
                    {
                        found = true;
                        returnSet.Add(orgScheme);
                        break;
                    }
                }

                if (!found)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProvider).ToString(), 
                        provision.DataproviderRef);
                }
            }

            return returnSet;
        }
		public virtual ISet<IRegistrationObject> GetRegistrations(
				IProvisionAgreementObject provision) {
			return GetRegistrations(provision.AsReference());
		}