public ComplexDataQuerySelectionGroupImpl(ISet<IComplexDataQuerySelection> complexSelections, 
                                                    ISdmxDate dateFrom, OrderedOperator dateFromOperator, 
                                                    ISdmxDate dateTo, OrderedOperator dateToOperator, 
                                                    ISet<IComplexComponentValue> primaryMeasureValues)
        {
		    //check if the operator to be applied on the time has not the 'NOT_EQUAL' value
		    if (dateFromOperator.Equals(OrderedOperatorEnumType.NotEqual) || dateToOperator.Equals(OrderedOperatorEnumType.NotEqual))
			    throw new SdmxSemmanticException(ExceptionCode.QuerySelectionIllegalOperator);
		
		    if (complexSelections == null) 
            {
			    return;
		    }
		
		    this._dateFrom = dateFrom;
		    this._dateFromOperator = dateFromOperator;
		    this._dateTo = dateTo;
		    this._dateToOperator = dateToOperator;	
		    this._complexSelections = complexSelections;
		    this._primaryMeasureValues = primaryMeasureValues;
		
		    // Add each of the Component Selections to the selection concept map. 
		    foreach (IComplexDataQuerySelection compSel in _complexSelections) 
            {
			    if (_complexSelectionForConcept.ContainsKey(compSel.ComponentId)) 
                {
				    //TODO Does this require a exception, or can the code selections be merged?
				    throw new ArgumentException("Duplicate concept");
			    }
			    _complexSelectionForConcept.Add(compSel.ComponentId, compSel);
		    }		
	    }
	    public ComplexComponentValueImpl(string value, OrderedOperator orderedOperator,  SdmxStructureEnumType componentType)
        {
		    if (componentType.Equals(SdmxStructureEnumType.TimeDimension) && orderedOperator.Equals(OrderedOperatorEnumType.NotEqual))
			    throw new SdmxSemmanticException(ExceptionCode.QuerySelectionIllegalOperator);

		    this._value =value;
		    if (orderedOperator!=null)
			    this._orderedOperator = orderedOperator;
		    else
			    this._orderedOperator = OrderedOperator.GetFromEnum(OrderedOperatorEnumType.Equal);
	    }
	    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>
 /// Gets SQL operator from the given SDMX OrderedOperator
 /// </summary>
 /// <param name="ord">
 /// The OrderedOperator
 /// </param>
 /// <returns>
 /// An string containing the sql query ordered operator 
 /// </returns>
 private static string GetSqlOrderedOperator(OrderedOperator ord)
 {
     switch (ord.EnumType)
     {
         case OrderedOperatorEnumType.Equal:
             return "=";
         case OrderedOperatorEnumType.GreaterThan:
             return ">";
         case OrderedOperatorEnumType.GreaterThanOrEqual:
             return ">=";
         case OrderedOperatorEnumType.LessThan:
             return "<";
         case OrderedOperatorEnumType.LessThanOrEqual:
             return "<=";
         case OrderedOperatorEnumType.NotEqual:
             return "!=";
         default:
             break;
     }
     return "=";
 }
 /// <summary>
 /// Id adds a selection group only if it has at least one of the following date from, date to, valid collection of primary measure values, valid collection of complex selections. <br>
 /// A collection is considered valid when it is not null and contains at least one element.
 /// </summary>
 /// <param name="complexSelections">
 /// The selections.
 /// </param>
 /// <param name="dateFrom">
 /// The date from.
 /// </param>
 /// <param name="dateFromOperator">
 /// The date from operator.
 /// </param>
 /// <param name="dateTo">
 /// The date to.
 /// </param>
 /// <param name="dateToOperator">
 /// The date to operator.
 /// </param>
 /// <param name="primaryMeasureValues">
 /// The primary measure values.
 /// </param>
 /// <param name="complexDataQuerySelectionGroups">
 /// The complex data query selection groups.
 /// </param>
 private void AddGroupIfSelectionsExist(ISet<IComplexDataQuerySelection> complexSelections,
                                         ISdmxDate dateFrom, OrderedOperator dateFromOperator,
                                         ISdmxDate dateTo, OrderedOperator dateToOperator,
                                         ISet<IComplexComponentValue> primaryMeasureValues,
                                         ISet<IComplexDataQuerySelectionGroup> complexDataQuerySelectionGroups)
 {
     if (ObjectUtil.ValidCollection(complexSelections) || dateFrom != null || dateTo != null || ObjectUtil.ValidCollection(primaryMeasureValues))
     {
         complexDataQuerySelectionGroups.Add(new ComplexDataQuerySelectionGroupImpl(complexSelections, dateFrom, dateFromOperator, dateTo, dateToOperator, primaryMeasureValues));
     }
 }