/// <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>
        /// 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);
            }
        }
        public void TestDataWriterEngineMultiDataset(DataEnumType format)
        {
            string outfile = string.Format("{0}-multi.xml", format);
            DataType fromEnum = DataType.GetFromEnum(format);
            var objects = GetSdmxObjects();
            IDataStructureObject dataStructureObject = objects.DataStructures.First();
            var dataWriterManager = new DataWriterManager();
            var startTime = new DateTime(2012, 1, 1);
            
            using (Stream writer = File.Create(outfile))
            {
                using (IDataWriterEngine dataWriter = dataWriterManager.GetDataWriterEngine(new SdmxDataFormatCore(fromEnum), writer))
                {
                    var header = new HeaderImpl("IDTEST", "ZZ9");
                    dataWriter.WriteHeader(header);

                    IDatasetHeader dataSetHeader = new DatasetHeaderCore(
                        "UPDATE",
                        DatasetAction.GetFromEnum(DatasetActionEnumType.Replace),
                        new DatasetStructureReferenceCore(dataStructureObject.AsReference));
                    dataWriter.StartDataset(null, dataStructureObject, dataSetHeader);
                    dataWriter.StartSeries();
                    dataWriter.WriteSeriesKeyValue("FREQ", "M");
                    dataWriter.WriteSeriesKeyValue("REF_AREA", "DE");
                    dataWriter.WriteSeriesKeyValue("ADJUSTMENT", "N");
                    dataWriter.WriteSeriesKeyValue("STS_INDICATOR", "PROD");
                    dataWriter.WriteSeriesKeyValue("STS_ACTIVITY", "NS0030");
                    dataWriter.WriteSeriesKeyValue("STS_INSTITUTION", "1");
                    dataWriter.WriteSeriesKeyValue("STS_BASE_YEAR", "2000");
                    var getPeriod1 = GetPeriodFunc("M", startTime);
                    dataWriter.WriteAttributeValue("TIME_FORMAT", GetTimeFormat("M"));

                    for (int i = 0; i < 5; i++)
                    {
                        string period = getPeriod1(i);
                        dataWriter.WriteObservation(period, i.ToString(CultureInfo.InvariantCulture));
                        dataWriter.WriteAttributeValue("OBS_STATUS", "A");
                    }

                    IDatasetHeader dataSetHeaderDelete = new DatasetHeaderCore(
                        "DELETE",
                        DatasetAction.GetFromEnum(DatasetActionEnumType.Delete),
                        new DatasetStructureReferenceCore(dataStructureObject.AsReference));
                    dataWriter.StartDataset(null, dataStructureObject, dataSetHeaderDelete);
                    dataWriter.StartSeries();
                    dataWriter.WriteSeriesKeyValue("FREQ", "M");
                    dataWriter.WriteSeriesKeyValue("REF_AREA", "DE");
                    dataWriter.WriteSeriesKeyValue("ADJUSTMENT", "N");
                    dataWriter.WriteSeriesKeyValue("STS_INDICATOR", "PROD");
                    dataWriter.WriteSeriesKeyValue("STS_ACTIVITY", "NS0030");
                    dataWriter.WriteSeriesKeyValue("STS_INSTITUTION", "1");
                    dataWriter.WriteSeriesKeyValue("STS_BASE_YEAR", "2000");
                    var getPeriod = GetPeriodFunc("M", new DateTime(2006, 1, 1));

                    for (int i = 0; i < 5; i++)
                    {
                        string period = getPeriod(i);
                        dataWriter.WriteObservation(period, "NaN");
                    }

                    dataWriter.Close();
                }
            }

            if (fromEnum.BaseDataFormat.EnumType == BaseDataFormatEnumType.Generic)
            {
                var fileReadableDataLocation = new FileReadableDataLocation(outfile);

                XMLParser.ValidateXml(fileReadableDataLocation, fromEnum.SchemaVersion);
            }
        }