/// <summary>
        /// Sets the current dataflow.
        /// </summary>
        /// <param name="currentDataflow">
        /// The current dataflow.
        /// </param>
        private void SetCurrentDataflow(IDataflowObject currentDataflow)
        {
            this._currentDataflow = currentDataflow;

            // If the current dataset header does not reference a Dataflow then amend it
            if (this._datasetHeader == null)
            {
                this._datasetHeader = new DatasetHeaderCore(Guid.NewGuid().ToString(), DatasetActionEnumType.Information, new DatasetStructureReferenceCore(currentDataflow.AsReference));
            }
            else if (this._datasetHeader.DataProviderReference == null)
            {
                IDatasetStructureReference datasetStructureReference = new DatasetStructureReferenceCore(currentDataflow.AsReference);
                this._datasetHeader = this._datasetHeader.ModifyDataStructureReference(datasetStructureReference);
            }

            if (this._defaultDsd != null && this._defaultDsd.Urn.Equals(currentDataflow.DataStructureRef.TargetUrn))
            {
                this.SetCurrentDsd(this._defaultDsd);
            }
            else if (this._objectRetrieval != null)
            {
                this.SetCurrentDsd(this._objectRetrieval.GetMaintainableObject<IDataStructureObject>(currentDataflow.DataStructureRef.MaintainableReference) as ICrossSectionalDataStructureObject);
            }
        }
        /// <summary>
        /// Sets the current DSD.
        /// </summary>
        /// <param name="currentDsd">
        /// The current DSD.
        /// </param>
        protected void SetCurrentDsd(ICrossSectionalDataStructureObject currentDsd)
        {
            this._currentDsd = currentDsd;
            foreach (var component in currentDsd.Components)
            {
                this._conceptToComponentId[component.ConceptRef.FullId] = component.Id;
            }

            this._availableDimensions.AddRange(currentDsd.GetDimensions(SdmxStructureEnumType.Dimension).Select(dimension => dimension.Id));
            this._availableMeasureDimensions.AddRange(currentDsd.GetDimensions(SdmxStructureEnumType.MeasureDimension).Select(dimension => dimension.Id));
            this._availableCrossSectionalMeasures.AddRange(currentDsd.CrossSectionalMeasures.Select(measure => measure.Id));
            this._primaryMeasure = currentDsd.PrimaryMeasure.Id;
            if (currentDsd.TimeDimension != null)
            {
                this._timeDimensionId = currentDsd.TimeDimension.Id;
            }

            // If the current dataset header does not reference a DSD then amend it
            var datasetHeader = this._datasetHeader;
            if (datasetHeader != null && datasetHeader.DataStructureReference == null)
            {
                IDatasetStructureReference datasetStructureReference = new DatasetStructureReferenceCore(currentDsd.AsReference);
                this._datasetHeader = this._datasetHeader.ModifyDataStructureReference(datasetStructureReference);
            }
        }
        /// <summary>
        /// Retrieve data from a DDB and write it to the specified <paramref name="writer"/> This is the main public method of the DataRetriever class. It is called with a populated QueryBean (containing essentially an SDMX-ML Query) and a database Connection to a "Mapping Store" database. This method is responsible for: 
        /// <list type="bullet">
        /// <item>
        /// Retrieving the <see cref="MappingSetEntity"/> (the class containing the performed mappings), according to the provided Dataflow ID, from the "Mapping Store". Mapping Sets are defined on a Dataflow basis. Thus, this method checks the input QueryBean for the Dataflow that data are requested and fetches the appropriate
        /// <see cref="MappingSetEntity"/>. If no <see cref="MappingSetEntity"/> exists, an exception (<see cref="DataRetrieverException"/>) is thrown.
        /// </item>
        /// <item>
        /// Calling the method generating the appropriate SQL for the dissemination database.
        /// </item>
        /// <item>
        /// Calling the method that executes the generated SQL and uses the
        ///  <paramref name="writer"/>
        ///  to write the output.
        /// </item>
        /// </list>
        /// <note type="note">
        /// The "Data Retriever" expects exactly one Dataflow clause under the DataWhere clause, exactly one
        ///        DataFlowBean within the DataWhereBean (which in turn resides inside the incoming QueryBean).
        /// </note>
        /// </summary>
        /// <exception cref="DataRetrieverException">
        /// See the
        ///   <see cref="ErrorTypes"/>
        ///   for more details
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="query"/>
        ///   is null
        ///   -or-
        ///   <paramref name="writer"/>
        ///   is null
        /// </exception>
        /// <param name="query">
        /// The query bean for which data will be requested 
        /// </param>
        /// <param name="writer">
        /// The Cross Sectional writer 
        /// </param>
        /// <example>
        /// An example using this method in C# with <see cref="CrossSectionalWriter"/> 
        ///  <code source="ReUsingExamples\DataRetriever\ReUsingDataRetrieverCrossSectional.cs" lang="cs">
        /// </code>
        /// </example>
        public void GetData(IDataQuery dataQuery, ICrossSectionalWriterEngine dataWriter)
        {
            if (dataQuery == null)
            {
                throw new ArgumentNullException("query");
            }

            if (dataWriter == null)
            {
                throw new ArgumentNullException("writer");
            }

            try
            {
                Logger.Info(Resources.InfoDataRetrieverBBInvoked);
                Logger.Info(Resources.InfoOutput + dataWriter.GetType().Name);

                // validate input and initialize the mappingset entitiy
                MappingSetEntity mappingSet = this.Initialize(dataQuery);

                var info = new DataRetrievalInfoXS(mappingSet, dataQuery, this._connectionStringSettings, dataWriter)
                {
                    DefaultHeader = this._defaultHeader
                };
                ValidateMappingSet(info);
                this.WriteHeader(dataWriter, info);
                ICrossSectionalDataStructureObject crossDsd = dataQuery.DataStructure as ICrossSectionalDataStructureObject;

                //(SRA-345) 
                //DR the info from I*DataQuery. DimensionAtObservation to IDataWriterEngine.StartDataSet  
                IDatasetStructureReference dsr = new DatasetStructureReferenceCore("", dataQuery.DataStructure.AsReference, null, null, dataQuery.DimensionAtObservation);
                IDatasetHeader header = new DatasetHeaderCore(this._defaultHeader.DatasetId, this._defaultHeader.Action, dsr);

                dataWriter.StartDataset(dataQuery.Dataflow, crossDsd, header);

                this.GenerateSql(info, _sqlXsBuilder);

                // execute sql query.
                this.ExecuteSql(info, CrossSectionalQueryEngineManager.Instance.GetQueryEngine(info));

                // close output
                dataWriter.Close();
                Logger.Info(Resources.InfoEndDataRetrieverBBInvoked);
            }
            catch (DataRetrieverException)
            {
                throw;
            }
            catch (SdmxException)
            {
                throw;
            }
            catch (DbException ex)
            {
                Logger.Error(ex.ToString());
                throw new DataRetrieverException(ex,
                    SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError),
                    Resources.DataRetriever_ExecuteSqlQuery_Error_executing_generated_SQL_and_populating_SDMX_model);
                //ErrorTypes.DDB_CONNECTION_ERROR,
                //Resources.DataRetriever_ExecuteSqlQuery_Error_executing_generated_SQL_and_populating_SDMX_model,
                //ex);
            }
            catch (OutOfMemoryException)
            {
                throw;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new DataRetrieverException(ex,
                    SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError),
                    Resources.DataRetriever_ExecuteSqlQuery_Error_during_writing_responce);
                //ErrorTypes.WRITING_OUTPUT_ERROR,
                //Resources.DataRetriever_ExecuteSqlQuery_Error_during_writing_responce,
                //ex);
            }
        }
        /// <summary>
        /// Retrieve data from a DDB and write it to the specified <paramref name="writer"/> This is the main public method of the DataRetriever class. It is called with a populated QueryBean (containing essentially an SDMX-ML Query) and a database Connection to a "Mapping Store" database. This method is responsible for: 
        /// <list type="bullet">
        /// <item>
        /// Retrieving the <see cref="MappingSetEntity"/> (the class containing the performed mappings), according to the provided Dataflow ID, from the "Mapping Store". Mapping Sets are defined on a Dataflow basis. Thus, this method checks the input QueryBean for the Dataflow that data are requested and fetches the appropriate
        /// <see cref="MappingSetEntity"/>. If no <see cref="MappingSetEntity"/> exists, an exception (<see cref="DataRetrieverException"/>) is thrown.
        /// </item>
        /// <item>
        /// Calling the method generating the appropriate SQL for the dissemination database.
        /// </item>
        /// <item>
        /// Calling the method that executes the generated SQL and uses the
        ///  <paramref name="writer"/>
        ///  to write the output.
        /// </item>
        /// </list>
        /// <note type="note">
        /// The "Data Retriever" expects exactly one Dataflow clause under the DataWhere clause, exactly one
        ///        DataFlowBean within the DataWhereBean (which in turn resides inside the incoming QueryBean).
        /// </note>
        /// </summary>
        /// <exception cref="DataRetrieverException">
        /// See the
        ///   <see cref="ErrorTypes"/>
        ///   for more details
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="query"/>
        ///   is null
        ///   -or-
        ///   <paramref name="writer"/>
        ///   is null
        /// </exception>
        /// <param name="query">
        /// The query bean for which data will be requested 
        /// </param>
        /// <param name="writer">
        /// The <see cref="ISeriesWriter"/> (e.g. Compact, Generic) writer 
        /// </param>
        /// <example>
        /// An example using this method in C# with <see cref="CompactWriter"/> 
        /// <code source="ReUsingExamples\DataRetriever\ReUsingDataRetriever.cs" lang="cs">
        /// </code>
        /// An example using this method in C# with <see cref="GenericDataWriter"/> 
        /// <code source="ReUsingExamples\DataRetriever\ReUsingDataRetrieverGeneric.cs" lang="cs">
        /// </code>
        /// </example>
        public void GetData(IDataQuery dataQuery, IDsplDataWriterEngine dataWriter)
        {

            if (dataQuery == null)
            {
                throw new ArgumentNullException("query");
            }

            if (dataWriter == null)
            {
                throw new ArgumentNullException("writer");
            }

            try
            {
                Logger.Info(Resources.InfoDataRetrieverBBInvoked);
                Logger.Info(Resources.InfoOutput + dataWriter.GetType().Name);

                // validate input and initialize the mappingset entitiy
                MappingSetEntity mappingSet = this.Initialize(dataQuery);

                var info = new DataRetrievalInfoSeries(mappingSet, dataQuery, this._connectionStringSettings, dataWriter, this._sdmxSchemaVersion)
                {
                    DefaultHeader = this._defaultHeader
                };
                ValidateMappingSet(info);

                //Pietro 27/01
                //this.WriteHeader(dataWriter, info);

                //(SRA-345) 
                //DR the info from I*DataQuery. DimensionAtObservation to IDataWriterEngine.StartDataSet  
                IDatasetStructureReference dsr = new DatasetStructureReferenceCore("", dataQuery.DataStructure.AsReference, null, null, dataQuery.DimensionAtObservation);
                IDatasetHeader header = new DatasetHeaderCore(this._defaultHeader.DatasetId, this._defaultHeader.Action, dsr);

                //info.MappingSet.DataSet.Description.ToString()
                //info.MappingSet.Dataflow.Dsd.Id.ToString()
                dataWriter.SetDsdOrder(dataQuery.DataStructure);
                dataWriter.StartDataset(info.MappingSet.DataSet.Description.ToString(), dataQuery.Dataflow, dataQuery.DataStructure, header, null);

                // Generate sql query
                this.GenerateSql(info, _sqlBuilder);

                this.GenerateSql(info, SeriesDataSetSqlBuilder.Instance);

                this.GenerateSql(info, SeriesGroupSqlBuilder.Instance);                

                // execute sql query
                this.ExecuteSql(info, SeriesQueryEngineManager.Instance.GetQueryEngine(info));

                // close output
                dataWriter.Close();
                Logger.Info(Resources.InfoEndDataRetrieverBBInvoked);
            }
            catch (DataRetrieverException)
            {
                throw;
            }
            catch (SdmxException)
            {
                throw;
            }
            catch (DbException ex)
            {
                Logger.Error(ex.ToString());
                throw new DataRetrieverException(ex,
                    SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError),
                    Resources.DataRetriever_ExecuteSqlQuery_Error_executing_generated_SQL_and_populating_SDMX_model);
            }
            catch (OutOfMemoryException)
            {
                throw;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new DataRetrieverException(ex,
                    SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError),
                    Resources.DataRetriever_ExecuteSqlQuery_Error_during_writing_responce);
            }
        }
        /// <summary>
        /// Move to the next OBS.
        /// </summary>
        /// <param name="includeObs">
        /// if set to <c>true</c> [include OBS].
        /// </param>
        /// <returns>
        /// True if it successfully moves to the next OBS; otherwise false;
        /// </returns>
        protected override bool Next(bool includeObs)
        {
            while (this.Parser.Read())
            {
                var nodeType = this.Parser.NodeType;
                string nodeName;
                if (nodeType == XmlNodeType.Element)
                {
                    // TODO check why java uses ignore case for DataSet check since both SDMX v2.0 and v2.1 use the same casing.
                    nodeName = this.Parser.LocalName;
                    ElementNameTable elementName;
                    if (Enum.TryParse(nodeName, out elementName))
                    {
                        switch (elementName)
                        {
                            case ElementNameTable.DataSet:
                                this.DatasetPositionInternal = Api.Constants.DatasetPosition.Dataset;
                                this._attributesOnDatasetNode = new Dictionary<string, string>(StringComparer.Ordinal);
                                this.DatasetHeader = new DatasetHeaderCore(this.Parser, this.Header);
                                string dsdId = this.ProcessDatasetNode();
                                IDatasetStructureReference dataStructureReference = this.DatasetHeader.DataStructureReference;
                                IStructureReference structureReference = null;
                                string id = null;
                                Uri serviceUrl = null;
                                Uri structureUrl = null;
                                string dimensionAtObservation = null;
                                if (dataStructureReference != null)
                                {
                                    id = dataStructureReference.Id;
                                    serviceUrl = dataStructureReference.ServiceUrl;
                                    structureUrl = dataStructureReference.StructureUrl;
                                    dimensionAtObservation = dataStructureReference.DimensionAtObservation;
                                    structureReference = dataStructureReference.StructureReference;
                                }

                                if (structureReference == null)
                                {
                                    if (this.DefaultDsd != null && this.DefaultDsd.Id.Equals(dsdId))
                                    {
                                        structureReference = this.DefaultDsd.AsReference;
                                    }
                                    else
                                    {
                                        structureReference = new StructureReferenceImpl(null, dsdId, MaintainableObject.DefaultVersion, SdmxStructureEnumType.Dsd);
                                    }
                                }

                                dataStructureReference = new DatasetStructureReferenceCore(id, structureReference, serviceUrl, structureUrl, dimensionAtObservation);
                                this.DatasetHeader = this.DatasetHeader.ModifyDataStructureReference(dataStructureReference);
                                return true;
                            case ElementNameTable.Series:
                                StaxUtil.SkipToEndNode(this.RunAheadParser, ElementNameTable.SeriesKey.FastToString());
                                this.DatasetPositionInternal = Api.Constants.DatasetPosition.Series;
                                return true;
                            case ElementNameTable.Group:
                                StaxUtil.SkipToEndNode(this.RunAheadParser, ElementNameTable.GroupKey.FastToString());
                                this.DatasetPositionInternal = Api.Constants.DatasetPosition.Group;

                                // TODO test in Java it is possible to ignore the namespace. 
                                this.GroupId = this.Parser.GetAttribute(AttributeNameTable.type);
                                return true;
                            case ElementNameTable.Obs:
                                if (this.DatasetPositionInternal == Api.Constants.DatasetPosition.Series || this.DatasetPositionInternal == Api.Constants.DatasetPosition.Observation)
                                {
                                    if (includeObs)
                                    {
                                        this.DatasetPositionInternal = Api.Constants.DatasetPosition.Observation;
                                        return true;
                                    }

                                    continue;
                                }

                                this.DatasetPositionInternal = Api.Constants.DatasetPosition.ObservationAsSeries;
                                return true;
                            case ElementNameTable.Annotations:
                            case ElementNameTable.Attributes:
                                this.Parser.Skip();
                                break;
                            case ElementNameTable.KeyFamilyRef:
                            case ElementNameTable.Time:
                            case ElementNameTable.ObsValue:
                            case ElementNameTable.ObsDimension:
                            case ElementNameTable.SeriesKey:
                            case ElementNameTable.Value:
                            case ElementNameTable.GroupKey:
                                break;
                            default:
                                throw new SdmxSyntaxException("Unexpected Node in XML: " + nodeName);
                        }
                    }
                }
                else if (nodeType == XmlNodeType.EndElement)
                {
                    nodeName = this.Parser.LocalName;
                    if (ElementNameTable.Series.Is(nodeName) || ElementNameTable.Group.Is(nodeName))
                    {
                        this.DatasetPositionInternal = Api.Constants.DatasetPosition.Null;
                    }
                }
            }

            this.HasNext = false;
            return false;
        }
        /// <summary>
        /// Sets the current DSD.
        /// </summary>
        /// <param name="currentDsd">
        /// The current DSD.
        /// </param>
        protected virtual void SetCurrentDsd(IDataStructureObject currentDsd)
        {
            this._currentDsd = currentDsd;

            // If the current dataset header does not reference a DSD then amend it
            if (this._datasetHeader.DataStructureReference == null)
            {
                IDatasetStructureReference datasetStructureReference = new DatasetStructureReferenceCore(currentDsd.AsReference);
                this._datasetHeader = this._datasetHeader.ModifyDataStructureReference(datasetStructureReference);
            }
        }