/// <summary>
        /// Initializes a new instance of the <see cref="TimeDimensionDateType"/> class. 
        /// Builds a TimeDimensionDateType
        /// </summary>
        /// <param name="mapping">
        /// The mapping of TimeDimension component
        /// </param>
        /// <param name="expression">
        /// The expression that is used in this mapping
        /// </param>
        /// <param name="databaseType">
        /// The dissemination database type
        /// </param>
        public TimeDimensionDateType(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
            : base(mapping, expression, databaseType)
        {
            string provider = DatabaseType.GetProviderName(databaseType);
            string cast = DatabaseType.DatabaseSettings[provider].DateCast;

            /*
            if (databaseType.Equals(DatabaseType.Mappings.Oracle.Name, StringComparison.OrdinalIgnoreCase)
                || databaseType.Equals(DatabaseType.Mappings.MySql.Name, StringComparison.OrdinalIgnoreCase))
            {
                cast = "DATE";
            }
            */
            var dateColumnSysId = expression.DateColumnSysId;
            string columnName = GetColumnName(mapping, dateColumnSysId);
            this._startWhereFormat = string.Format(
                CultureInfo.InvariantCulture, "({0}>= {2}'{1}')", columnName, "{0}", cast);
            this._endWhereFormat = string.Format(
                CultureInfo.InvariantCulture, "({0}<= {2}'{1}')", columnName, "{0}", cast);

            this._resultParsingMap.Add(typeof(DateTime), x => (DateTime)x);
            this._resultParsingMap.Add(typeof(long), x => new DateTime((long)x));
            this._resultParsingMap.Add(
                typeof(string), 
                x =>
                    {
                        DateTime time;
                        return DateTime.TryParse((string)x, CultureInfo.InvariantCulture, DateTimeStyles.None, out time)
                                   ? DateTime.MinValue
                                   : time;
                    });

            this._fieldOrdinals = new TimeTranscodingFieldOrdinal(mapping, this.Expression);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TimeDimensionConstant"/> class. 
 /// Initialize an new instance of the TimeDimensionMapping based class
 /// </summary>
 /// <param name="mapping">
 /// The time dimension mapping
 /// </param>
 /// <param name="expression">
 /// It is not used in this implementation 
 /// </param>
 /// <param name="databaseType">
 /// The dissemination database vendor from  DB_CONNECTION.DB_TYPE at Mapping Store database. It is used to determine the substring command to use
 /// </param>
 /// <exception cref="TranscodingException">
 /// It is not used in this implementation
 /// </exception>
 public TimeDimensionConstant(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
     : base(mapping, expression, databaseType)
 {
     this._fromWhere = string.Format(
         CultureInfo.InvariantCulture, " ( '{0}' >= '{1}' )", mapping.Constant, "{0}");
     this._toWhere = string.Format(CultureInfo.InvariantCulture, " ( '{0}' <= '{1}' )", mapping.Constant, "{0}");
     this._equalsWhere = string.Format(
         CultureInfo.InvariantCulture, " ( '{0}' = '{1}' )", mapping.Constant, "{0}");
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TimeDimension1To1"/> class. 
 /// Initialize an new instance of the TimeDimensionMapping based class
 /// </summary>
 /// <param name="mapping">
 /// The time dimension mapping
 /// </param>
 /// <param name="expression">
 /// It is not used in this implementation 
 /// </param>
 /// <param name="databaseType">
 /// The dissemination database vendor from  DB_CONNECTION.DB_TYPE at Mapping Store database. It is used to determine the substring command to use
 /// </param>
 /// <exception cref="TranscodingException">
 /// It is not used in this implementation
 /// </exception>
 public TimeDimension1To1(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
     : base(mapping, expression, databaseType)
 {
     this._fromWhere = string.Format(
         CultureInfo.InvariantCulture, " ( {0} >= '{1}' )", mapping.Columns[0].Name, "{0}");
     this._toWhere = string.Format(
         CultureInfo.InvariantCulture, " ( {0} <= '{1}' )", mapping.Columns[0].Name, "{0}");
     this._equalsWhere = string.Format(
         CultureInfo.InvariantCulture, " ( {0} = '{1}' )", mapping.Columns[0].Name, "{0}");
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TimeDimensionMapping"/> class. 
 /// Initialize an new instance of the TimeDimensionMapping based class
 /// </summary>
 /// <param name="mapping">
 /// The time dimension mapping
 /// </param>
 /// <param name="expression">
 /// The TRANSCODING.EXPRESSION contents
 /// </param>
 /// <param name="databaseType">
 /// The dissemination database vendor from DB_CONNECTION.DB_TYPE at Mapping Store database. It is used to determine the substring command to use
 /// </param>
 /// <exception cref="TranscodingException">
 /// Occurs when transcoding cannot performed due to incorrect mapping store data
 /// </exception>
 protected TimeDimensionMapping(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
 {
     this.Mapping = mapping;
     this.Component = mapping.Components[0];
     this._expression = expression;
     this.SetDbType(databaseType);
     if (expression != null)
     {
         this._periodicity = PeriodicityFactory.Create(expression.Freq);
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TimeTranscodingFieldOrdinal"/> class. 
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 /// <param name="mapping">
 /// The mapping.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 public TimeTranscodingFieldOrdinal(MappingEntity mapping, TimeExpressionEntity expression)
 {
     this._yearColumn = new NameOrdinal(GetColumnName(mapping, expression.YearColumnSysId));
     this._periodColumn = new NameOrdinal(GetColumnName(mapping, expression.PeriodColumnSysId));
     this._dateColumn = new NameOrdinal(GetColumnName(mapping, expression.DateColumnSysId));
     if (this._yearColumn.IsSet)
     {
         this._nameOrdinals = this._periodColumn.IsSet ? new[] { this._yearColumn, this._periodColumn } : new[] { this._yearColumn };
     }
     else
     {
         this._nameOrdinals = new[] { this._dateColumn };
     }
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="TimeDimension1Column"/> class. 
        /// </summary>
        /// <param name="mapping">
        /// The time dimension mapping
        /// </param>
        /// <param name="expression">
        /// The TRANSCODING.EXPRESSION contents
        /// </param>
        /// <param name="databaseType">
        /// The dissemination database vendor from  DB_CONNECTION.DB_TYPE at Mapping Store database. It is used to determine the substring command to use
        /// </param>
        /// <exception cref="TranscodingException">
        /// Occurs when transcoding cannot performed due to incorrect mapping store data
        /// </exception>
        public TimeDimension1Column(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
            : base(mapping, expression, databaseType)
        {
            this._periodLocalCode = new CodeCollection();
            string yearPeriodColumn = GetColumnName(mapping, expression.YearColumnSysId);
            string yearOnlyStart = this.CreateSubStringClause(yearPeriodColumn, expression.YearStart + 1, expression.YearLength, ">=");
            string yearOnlyEnd = this.CreateSubStringClause(yearPeriodColumn, expression.YearStart + 1, expression.YearLength, "<=");

            string whereFormat = this.CreateSubStringClause(yearPeriodColumn, expression.PeriodStart + 1, expression.PeriodLength, "=");

            string yearOnlyWhereFormat = this.CreateSubStringClause(yearPeriodColumn, expression.YearStart + 1, expression.YearLength, "=");

            this._whereBuilder = new TimeTranscodingWhereBuilder(this.Periodicity, this.Expression, whereFormat, yearOnlyEnd, yearOnlyStart, yearOnlyWhereFormat);
            this._fieldOrdinals = new TimeTranscodingFieldOrdinal(mapping, this.Expression);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TimeDimension2Column"/> class. 
        /// </summary>
        /// <param name="mapping">
        /// The time dimension mapping
        /// </param>
        /// <param name="expression">
        /// The TRANSCODING.EXPRESSION contents
        /// </param>
        /// <param name="databaseType">
        /// The dissemination database vendor from  DB_CONNECTION.DB_TYPE at Mapping Store database. It is used to determine the substring command to use
        /// </param>
        /// <exception cref="TranscodingException">
        /// Occurs when transcoding cannot performed due to incorrect mapping store data
        /// </exception>
        public TimeDimension2Column(MappingEntity mapping, TimeExpressionEntity expression, string databaseType)
            : base(mapping, expression, databaseType)
        {
            string yearOnlyWhereFormat;
            string yearOnlyStart;
            string yearOnlyEnd;
            string whereFormat;
            this._periodLocalCode = new CodeCollection();
            string yearColumn = GetColumnName(mapping, expression.YearColumnSysId);
            string periodColumn = GetColumnName(mapping, expression.PeriodColumnSysId);

            string periodClause = expression.PeriodLength == 0
                                      ? string.Format(FormatProvider, "( {0} = '{1}' )", periodColumn, "{0}")
                                      : this.CreateSubStringClause(periodColumn, expression.PeriodStart + 1, expression.PeriodLength, "=");

            if (expression.YearLength == 0)
            {
                yearOnlyStart = string.Format(FormatProvider, " ( {0} >= '{1}' )", yearColumn, "{0}");
                yearOnlyEnd = string.Format(FormatProvider, " ( {0} <= '{1}' )", yearColumn, "{0}");
                yearOnlyWhereFormat = string.Format(FormatProvider, "( {0} = '{1}' )", yearColumn, "{0}");

                // whereFormat = String.Format(FormatProvider,"({0} = '{1}' and {2} )",yearColumn, "{0}",periodClause);
                whereFormat = periodClause;
            }
            else
            {
                yearOnlyStart = this.CreateSubStringClause(yearColumn, expression.YearStart + 1, expression.YearLength, ">=");
                yearOnlyEnd = this.CreateSubStringClause(yearColumn, expression.YearStart + 1, expression.YearLength, "<=");

                whereFormat = periodClause;
                yearOnlyWhereFormat = this.CreateSubStringClause(yearColumn, expression.YearStart + 1, expression.YearLength, "=");
            }

            this._whereBuilder = new TimeTranscodingWhereBuilder(this.Periodicity, this.Expression, whereFormat, yearOnlyEnd, yearOnlyStart, yearOnlyWhereFormat);
            this._fieldOrdinals = new TimeTranscodingFieldOrdinal(mapping, this.Expression);
        }
        /// <summary>
        /// Gets the name of the column.
        /// </summary>
        /// <param name="mapping">
        /// The mapping.
        /// </param>
        /// <param name="dateColumnSysId">
        /// The date column sys id.
        /// </param>
        /// <returns>
        /// The column name
        /// </returns>
        private static string GetColumnName(MappingEntity mapping, long dateColumnSysId)
        {
            if (dateColumnSysId > 0)
            {
                return mapping.Columns.First(entity => entity.SysId == dateColumnSysId).Name;
            }

            return null;
        }
        /// <summary>
        /// Retrieve time transcoding and populate the <paramref name="timeDimensionMapping"/>.
        /// </summary>
        /// <param name="mappingStoreDb">
        /// The mapping store DB.
        /// </param>
        /// <param name="timeDimensionMapping">
        /// The time dimension mapping.
        /// </param>
        private static void RetrieveTimeTranscoding(Database mappingStoreDb, MappingEntity timeDimensionMapping)
        {
            if (timeDimensionMapping == null)
            {
                return;
            }

            DbParameter parameter = mappingStoreDb.CreateInParameter(ParameterNameConstants.TranscodingId, DbType.Int64, timeDimensionMapping.Transcoding.SysId);

            using (DbCommand command = mappingStoreDb.GetSqlStringCommandFormat(MappingStoreSqlStatements.TimeTranscoding, parameter))
            {
                using (IDataReader reader = mappingStoreDb.ExecuteReader(command))
                {
                    int freqIdx = reader.GetOrdinal("FREQ");
                    int yearColIdIdx = reader.GetOrdinal("YEAR_COL_ID");
                    int periodColIdIdx = reader.GetOrdinal("PERIOD_COL_ID");
                    int dateColIdIdx = reader.GetOrdinal("DATE_COL_ID");
                    int expressionIdx = reader.GetOrdinal("EXPRESSION");

                    var timeTranscodingCollection = timeDimensionMapping.Transcoding.TimeTranscodingCollection;
                    while (reader.Read())
                    {
                        var timeTranscoding = timeTranscodingCollection.Add(DataReaderHelper.GetString(reader, freqIdx));
                        timeTranscoding.YearColumnId = DataReaderHelper.GetInt64(reader, yearColIdIdx);
                        timeTranscoding.PeriodColumnId = DataReaderHelper.GetInt64(reader, periodColIdIdx);
                        timeTranscoding.DateColumnId = DataReaderHelper.GetInt64(reader, dateColIdIdx);
                        timeTranscoding.Expression = DataReaderHelper.GetString(reader, expressionIdx);
                    }
                }
            }
        }
        /// <summary>
        /// Retrieve TimeDimension transcoding, if <paramref name="timeDimensionMapping"/> is null
        /// </summary>
        /// <param name="mappingStoreDb">
        /// The mapping store DB.
        /// </param>
        /// <param name="timeDimensionMapping">
        /// The time dimension mapping.
        /// </param>
        private static void RetrieveTimeDimensionTranscoding(
            Database mappingStoreDb, MappingEntity timeDimensionMapping)
        {
            if (timeDimensionMapping == null)
            {
                return;
            }

            RetrieveTimeTranscoding(mappingStoreDb, timeDimensionMapping);
            TimeTranscodingCollection timeTranscodingCollection = timeDimensionMapping.Transcoding.TimeTranscodingCollection;
            if (timeTranscodingCollection.Count == 1
                && TimeFormat.GetTimeFormatFromCodeId(timeTranscodingCollection[0].FrequencyValue).EnumType == TimeFormatEnumType.Year)
            {
                return;
            }

            var codelists = PeriodCodelist.PeriodCodelistIdMap;
            IDictionary<string, TimeTranscodingEntity> transcodingMap = new Dictionary<string, TimeTranscodingEntity>(StringComparer.Ordinal);
            foreach (var periodObject in codelists)
            {
                if (timeTranscodingCollection.Contains(periodObject.Key))
                {
                    var timeTranscodingEntity = timeTranscodingCollection[periodObject.Key];
                    if (timeTranscodingEntity.PeriodColumnId > 0)
                    {
                        var timeDimensionRules = new TranscodingRulesEntity();
                        timeDimensionRules.AddColumn(timeTranscodingEntity.PeriodColumnId, 0);
                        timeDimensionRules.AddComponent(timeDimensionMapping.Components[0].SysId, 0);
                        timeTranscodingEntity.TranscodingRules = timeDimensionRules;
                        transcodingMap.Add(periodObject.Value.Id, timeTranscodingEntity);
                    }

                }
            }

            DbParameter parameter = mappingStoreDb.CreateInParameter(ParameterNameConstants.TranscodingId, DbType.Int64, timeDimensionMapping.Transcoding.SysId);

            using (DbCommand command = mappingStoreDb.GetSqlStringCommandFormat(MappingStoreSqlStatements.TranscodingRulesTimeDimension, parameter))
            using (IDataReader dataReader = mappingStoreDb.ExecuteReader(command))
            {
                int dsdcodeIdx = dataReader.GetOrdinal("DSDCODE");
                int localcodeIdx = dataReader.GetOrdinal("LOCALCODE");
                int codelistId = dataReader.GetOrdinal("CODELIST_ID");

                while (dataReader.Read())
                {
                    var periodCodelist = DataReaderHelper.GetString(dataReader, codelistId);
                    TimeTranscodingEntity timeTranscodingEntity;
                    if (transcodingMap.TryGetValue(periodCodelist, out timeTranscodingEntity))
                    {
                        var timeDimensionRules = timeTranscodingEntity.TranscodingRules;
                        var dsdperiod = new CodeCollection();
                        var localperiod = new CodeCollection();
                        dsdperiod.Add(DataReaderHelper.GetString(dataReader, dsdcodeIdx));
                        localperiod.Add(DataReaderHelper.GetString(dataReader, localcodeIdx));
                        timeDimensionRules.Add(localperiod, dsdperiod);
                    }
                }
            }
        }
        /// <summary>
        /// This method retrieves a list of <see cref="MappingEntity"/> objects
        /// by the mapping set system identifier
        /// </summary>
        /// <param name="mappingStoreDb">
        /// The <see cref="Database"/> instance for Mapping Store database
        /// </param>
        /// <param name="mappingSet">
        /// The mapping set
        /// </param>
        private static void GetMappingsByMappingSetSysId(Database mappingStoreDb, MappingSetEntity mappingSet)
        {
            long sysId = mappingSet.SysId;

            var dictionary = new Dictionary<long, MappingEntity>();

            var componentMap = new Dictionary<long, ComponentEntity>();

            bool transcoded = false;

            MappingEntity timeDimensionMapping = null;

            AddToComponentMap(mappingSet.Dataflow.Dsd.Dimensions, componentMap);
            if (mappingSet.Dataflow.Dsd.TimeDimension != null)
            {
                componentMap.Add(mappingSet.Dataflow.Dsd.TimeDimension.SysId, mappingSet.Dataflow.Dsd.TimeDimension);
            }

            componentMap.Add(mappingSet.Dataflow.Dsd.PrimaryMeasure.SysId, mappingSet.Dataflow.Dsd.PrimaryMeasure);

            AddToComponentMap(mappingSet.Dataflow.Dsd.Attributes, componentMap);
            AddToComponentMap(mappingSet.Dataflow.Dsd.CrossSectionalMeasures, componentMap);

            string paramId = mappingStoreDb.BuildParameterName(ParameterNameConstants.IdParameter);

            var sqlCommand = new StringBuilder();

            // select
            sqlCommand.Append("SELECT CMAP.MAP_ID, CMAP.TYPE, CMAP.CONSTANT, CMAPCOMP.COMP_ID, TR.TR_ID, TR.EXPRESSION ");
           
            // from1
            sqlCommand.Append("FROM COMPONENT_MAPPING CMAP INNER JOIN  MAPPING_SET MSET ON MSET.MAP_SET_ID = CMAP.MAP_SET_ID INNER JOIN COM_COL_MAPPING_COMPONENT CMAPCOMP ON CMAPCOMP.MAP_ID = CMAP.MAP_ID ");
            sqlCommand.Append(" LEFT OUTER JOIN TRANSCODING TR ON TR.MAP_ID = CMAP.MAP_ID ");

            // where
            sqlCommand.AppendFormat(" WHERE MSET.MAP_SET_ID = {0} ", paramId);
            using (DbCommand command = mappingStoreDb.GetSqlStringCommand(sqlCommand.ToString()))
            {
                mappingStoreDb.AddInParameter(command, ParameterNameConstants.IdParameter, DbType.Int64, sysId);
                using (IDataReader dataReader = mappingStoreDb.ExecuteReader(command))
                {
                    int mapID = dataReader.GetOrdinal("MAP_ID");
                    int type = dataReader.GetOrdinal("TYPE");
                    int constant = dataReader.GetOrdinal("CONSTANT");
                    int compIDIdx = dataReader.GetOrdinal("COMP_ID");
                    int tridIdx = dataReader.GetOrdinal("TR_ID");
                    int exprIdx  = dataReader.GetOrdinal("EXPRESSION");
                    while (dataReader.Read())
                    {
                        // get existing or create new mapping object
                        long mapId = DataReaderHelper.GetInt64(dataReader, mapID);
                        MappingEntity mapping;
                        if (!dictionary.TryGetValue(mapId, out mapping))
                        {
                            // create new mapping and append it to the mapping set
                            mapping = new MappingEntity(mapId) { MappingType = DataReaderHelper.GetString(dataReader, type), Constant = DataReaderHelper.GetString(dataReader, constant) };

                            long trid = DataReaderHelper.GetInt64(dataReader, tridIdx);
                            if (trid > 0)
                            {
                                mapping.Transcoding = new TranscodingEntity(trid) { Expression = DataReaderHelper.GetString(dataReader, exprIdx) };
                                transcoded = true;
                            }

                            dictionary.Add(mapId, mapping);
                            mappingSet.Mappings.Add(mapping);
                        }

                        long componentSysId = DataReaderHelper.GetInt64(dataReader, compIDIdx);

                        ComponentEntity component;
                        if (componentMap.TryGetValue(componentSysId, out component))
                        {
                            mapping.Components.Add(component);
                            if (component.Equals(mappingSet.Dataflow.Dsd.TimeDimension) && mapping.Transcoding != null)
                            {
                                timeDimensionMapping = mapping;
                            }
                        }
                    }
                }
            }

            // second select
            sqlCommand = new StringBuilder();
            sqlCommand.Append(
                "SELECT CMAP.MAP_ID, CMAP.TYPE, CMAP.CONSTANT, DSCOL.COL_ID, DSCOL.NAME, DSCOL.DS_ID ");
            sqlCommand.Append(
                "FROM COMPONENT_MAPPING CMAP, MAPPING_SET MSET, COM_COL_MAPPING_COLUMN CMAPCOL, DATASET_COLUMN DSCOL ");
            sqlCommand.Append("WHERE MSET.MAP_SET_ID = CMAP.MAP_SET_ID ");
            sqlCommand.Append("AND CMAP.MAP_ID = CMAPCOL.MAP_ID ");
            sqlCommand.Append("AND CMAPCOL.COL_ID = DSCOL.COL_ID ");
            sqlCommand.AppendFormat("AND MSET.MAP_SET_ID = {0} ", paramId);

            using (DbCommand command = mappingStoreDb.GetSqlStringCommand(sqlCommand.ToString()))
            {
                mappingStoreDb.AddInParameter(command, ParameterNameConstants.IdParameter, DbType.Int64, sysId);
                using (IDataReader dataReader = mappingStoreDb.ExecuteReader(command))
                {
                    int mapID = dataReader.GetOrdinal("MAP_ID");
                    int type = dataReader.GetOrdinal("TYPE");
                    int constant = dataReader.GetOrdinal("CONSTANT");
                    int colIDIdx = dataReader.GetOrdinal("COL_ID");
                    int nameIdx = dataReader.GetOrdinal("NAME");
                    ////int descIdx = dataReader.GetOrdinal("DESCRIPTION");
                    while (dataReader.Read())
                    {
                        // get existing or create new mapping object
                        long mapId = DataReaderHelper.GetInt64(dataReader, mapID);
                        MappingEntity mapping;
                        if (!dictionary.TryGetValue(mapId, out mapping))
                        {
                            // create new mapping and append it to the mapping set
                            mapping = new MappingEntity(mapId) { MappingType = DataReaderHelper.GetString(dataReader, type), Constant = DataReaderHelper.GetString(dataReader, constant) };

                            dictionary.Add(mapId, mapping);
                            mappingSet.Mappings.Add(mapping);
                        }

                        var column = new DataSetColumnEntity(DataReaderHelper.GetInt64(dataReader, colIDIdx)) { Name = DataReaderHelper.GetString(dataReader, nameIdx) };

                        // dsColumn.SysId = DataReaderHelper.GetInt64(dataReader, "DS_ID");
                        ////column.Description = DataReaderHelper.GetString(dataReader, descIdx);

                        mapping.Columns.Add(column);
                    }
                }
            }
            
            if (transcoded)
            {
                GetTranscodingRulesByMapSetId(mappingStoreDb, sysId, timeDimensionMapping, dictionary);
                RetrieveTimeDimensionTranscoding(mappingStoreDb, timeDimensionMapping);
            }
        }
        /// <summary>
        /// The method retrieves the <see cref="TranscodingRulesEntity"/> object
        /// by the transcoding system identifier
        /// </summary>
        /// <param name="mappingStoreDb">
        /// The <see cref="Database"/> instance for Mapping Store database
        /// </param>
        /// <param name="sysId">
        /// The mapping set with the specified system identifier
        /// </param>
        /// <param name="timeDimensionMapping">
        /// The TRANSCODING.TR_ID value of the TimeDimension, if there is TimeDimension and is transcoded; otherwise set to null 
        /// </param>
        /// <param name="mappingsMap">
        /// The map between COMPONENT_MAPPING.MAP_ID value and MappingEntity 
        /// </param>
        private static void GetTranscodingRulesByMapSetId(Database mappingStoreDb, long sysId, MappingEntity timeDimensionMapping, IDictionary<long, MappingEntity> mappingsMap)
        {
            string paramId = mappingStoreDb.BuildParameterName(ParameterNameConstants.IdParameter);
            string timeDimensionTranscodingIdParam = mappingStoreDb.BuildParameterName(ParameterNameConstants.TranscodingId);

            object timedimensionID = timeDimensionMapping == null ? (object)null : timeDimensionMapping.Transcoding.SysId;

            // holds the dsd codes by rule
            var componentsByRule = new Dictionary<long, CodeCollection>();

            string sql = string.Format(
               CultureInfo.InvariantCulture,
               MappingStoreSqlStatements.TranscodingRulesDsdCodes,
               paramId,
               timeDimensionTranscodingIdParam);

            using (DbCommand command = mappingStoreDb.GetSqlStringCommand(sql))
            {
                mappingStoreDb.AddInParameter(command, ParameterNameConstants.IdParameter, DbType.Int64, sysId);
                mappingStoreDb.AddInParameter(command, ParameterNameConstants.TranscodingId, DbType.Int64, timedimensionID);

                using (IDataReader dataReader = mappingStoreDb.ExecuteReader(command))
                {
                    int pos = 0;

                    long prevMapId = -1;

                    TranscodingRulesEntity currentRules = null;
                    long firstTrRuleID = -1;
                    long curTrRuleID = -1;
                    long prevTrRuleID = -1;
                    
                    var componentList = new CodeCollection();

                    int ruleIDIdx = dataReader.GetOrdinal("TR_RULE_ID");
                    int componentIdx = dataReader.GetOrdinal("COMPONENT");
                    int codeIdx = dataReader.GetOrdinal("CODE");
                    int mapIdIdx = dataReader.GetOrdinal("MAP_ID");
                    while (dataReader.Read())
                    {
                        long curMapId = DataReaderHelper.GetInt64(dataReader, mapIdIdx);
                        if (prevMapId != curMapId || currentRules == null)
                        {
                            prevMapId = curMapId;
                            if (curTrRuleID > -1)
                            {
                                componentsByRule.Add(curTrRuleID, componentList);
                            }

                            componentList = new CodeCollection();
                            firstTrRuleID = -1;
                            prevTrRuleID = -1;
                            pos = 0;
                            MappingEntity curretMapping = mappingsMap[curMapId];
                            currentRules = new TranscodingRulesEntity();
                            curretMapping.Transcoding.TranscodingRules = currentRules;
                        }

                        curTrRuleID = DataReaderHelper.GetInt64(dataReader, ruleIDIdx);
                        if (firstTrRuleID == -1 || firstTrRuleID == curTrRuleID)
                        {
                            firstTrRuleID = curTrRuleID;
                            prevTrRuleID = curTrRuleID;
                            currentRules.AddComponent(DataReaderHelper.GetInt64(dataReader, componentIdx), pos);

                            pos++;
                        }
                        else if (prevTrRuleID != curTrRuleID)
                        {
                            componentsByRule.Add(prevTrRuleID, componentList);
                            componentList = new CodeCollection();
                            prevTrRuleID = curTrRuleID;
                        }

                        componentList.Add(DataReaderHelper.GetString(dataReader, codeIdx));
                    }

                    if (curTrRuleID > -1)
                    {
                        componentsByRule.Add(curTrRuleID, componentList);
                    }
                }
            }

            if (componentsByRule.Count > 0)
            {
                sql = string.Format(
              CultureInfo.InvariantCulture,
              MappingStoreSqlStatements.TranscodingRulesLocalCodes,
              paramId,
              timeDimensionTranscodingIdParam);
                using (DbCommand command = mappingStoreDb.GetSqlStringCommand(sql))
                {
                    mappingStoreDb.AddInParameter(command, ParameterNameConstants.IdParameter, DbType.Int64, sysId);
                    mappingStoreDb.AddInParameter(command, ParameterNameConstants.TranscodingId, DbType.Int64, timedimensionID);

                    using (IDataReader dataReader = mappingStoreDb.ExecuteReader(command))
                    {
                        long prevMapId = -1;

                        int pos = 0;
                        TranscodingRulesEntity currentRules = null;
                        long firstTrRuleID = -1;
                        long curTrRuleID = -1;
                        long prevTrRuleID = -1;
                        var columnList = new CodeCollection();

                        int ruleIDIdx = dataReader.GetOrdinal("TR_RULE_ID");
                        int columnIdx = dataReader.GetOrdinal("LOCAL_COLUMN");
                        int codeIdx = dataReader.GetOrdinal("CODE");
                        int mapIdIdx = dataReader.GetOrdinal("MAP_ID");
                        while (dataReader.Read())
                        {
                            long curMapId = DataReaderHelper.GetInt64(dataReader, mapIdIdx);
                            if (prevMapId != curMapId || currentRules == null)
                            {
                                prevMapId = curMapId;
                                if (curTrRuleID > -1 && currentRules != null)
                                {
                                    currentRules.Add(columnList, componentsByRule[curTrRuleID]);
                                }

                                firstTrRuleID = -1;
                                prevTrRuleID = -1;
                                pos = 0;
                                columnList = new CodeCollection();
                                MappingEntity curretMapping = mappingsMap[curMapId];
                                currentRules = curretMapping.Transcoding.TranscodingRules;
                            }

                            curTrRuleID = DataReaderHelper.GetInt64(dataReader, ruleIDIdx);
                            if (firstTrRuleID == -1 || firstTrRuleID == curTrRuleID)
                            {
                                firstTrRuleID = curTrRuleID;
                                prevTrRuleID = curTrRuleID;
                                currentRules.AddColumn(DataReaderHelper.GetInt64(dataReader, columnIdx), pos);
                                pos++;
                            }
                            else if (prevTrRuleID != curTrRuleID)
                            {
                                currentRules.Add(columnList, componentsByRule[prevTrRuleID]);
                                columnList = new CodeCollection();
                                prevTrRuleID = curTrRuleID;
                            }

                            columnList.Add(DataReaderHelper.GetString(dataReader, codeIdx));
                        }

                        if (curTrRuleID > -1 && currentRules != null)
                        {
                            currentRules.Add(columnList, componentsByRule[curTrRuleID]);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Creates the appropriate Time Dimension Mapping object <see cref="ITimeDimension"/>  based on the mapping from the mapping store
        /// e.g. it will create a different object if TimeDimension is mapped to one column, different if it is mapped two column and different if the column is Date type
        /// </summary>
        /// <param name="mapping">
        /// The mapping entity<see cref="MappingEntity"/> of the Time Dimension component
        /// </param>
        /// <param name="frequencyComponentMapping">
        /// The frequency component mapping.
        /// </param>
        /// <param name="databaseType">
        /// The dissemination database vendor. Is needed to generate the correct SQL query where conditions
        /// </param>
        /// <returns>
        /// An Time Dimension Transcoding object<see cref="ITimeDimension"/>
        /// </returns>
        public static ITimeDimension Create(MappingEntity mapping, IComponentMapping frequencyComponentMapping, string databaseType)
        {
            ITimeDimension timeDimensionTranscoding = null;
            if (mapping.Transcoding == null)
            {
                timeDimensionTranscoding = new TimeDimensionSingleFrequency(CreateTimeDimensionMapping(mapping, databaseType));
            }
            else if (mapping.Transcoding.TimeTranscodingCollection.Count == 1)
            {
                timeDimensionTranscoding = new TimeDimensionSingleFrequency(CreateTranscodedTimeDimensionMapping(mapping, databaseType, mapping.Transcoding.TimeTranscodingCollection.First()));
            }
            else if (mapping.Transcoding.TimeTranscodingCollection.Count > 1)
            {
                var timeDimensionMappings = new Dictionary<string, ITimeDimensionMapping>(StringComparer.Ordinal);
                foreach (var transcodingEntity in mapping.Transcoding.TimeTranscodingCollection)
                {
                    var timeDimensionSubTranscoding = CreateTranscodedTimeDimensionMapping(mapping, databaseType, transcodingEntity);
                    timeDimensionMappings[transcodingEntity.FrequencyValue] = timeDimensionSubTranscoding;
                }
                
                timeDimensionTranscoding = new TimeDimensionMultiFrequency(timeDimensionMappings, frequencyComponentMapping);
            }

            if (timeDimensionTranscoding != null)
            {
                timeDimensionTranscoding.Component = mapping.Components[0];
                timeDimensionTranscoding.Mapping = mapping;
            }

            return timeDimensionTranscoding;
        }
        /// <summary>
        /// Create time dimension mapping without transcoding
        /// </summary>
        /// <param name="mapping">
        /// The mapping entity<see cref="MappingEntity"/> of the Time Dimension component
        /// </param>
        /// <param name="databaseType">
        /// The dissemination database vendor. Is needed to generate the correct SQL query where conditions
        /// </param>
        /// <exception cref="TranscodingException">
        /// Incomplete Mapping. N column Time Dimension mapping without transcoding is not supported, where N not in 0,1
        /// </exception>
        /// <returns>
        /// An Time Dimension Transcoding object<see cref="ITimeDimension"/>
        /// </returns>
        private static ITimeDimensionMapping CreateTimeDimensionMapping(MappingEntity mapping, string databaseType)
        {
            ITimeDimensionMapping timeDimensionTranscoding;
            switch (mapping.Columns.Count)
            {
                case 1:
                    timeDimensionTranscoding = new TimeDimension1To1(mapping, null, databaseType);
                    break;
                case 0:
                    timeDimensionTranscoding = new TimeDimensionConstant(mapping, null, databaseType);
                    break;
                default:
                    throw new TranscodingException(
                        string.Format(
                            CultureInfo.CurrentCulture, 
                            ErrorMessages.TimeDimensionUnsupportedMappingFormat1, 
                            mapping.Columns.Count)); // MAT-496
            }

            return timeDimensionTranscoding;
        }
 /// <summary>
 /// Gets the name of the column.
 /// </summary>
 /// <param name="mapping">The mapping.</param>
 /// <param name="dateColumnSysId">The date column sys id.</param>
 /// <returns>The column name</returns>
 protected static string GetColumnName(MappingEntity mapping, long dateColumnSysId)
 {
     return mapping.Columns.First(entity => entity.SysId == dateColumnSysId).Name;
 }
        /// <summary>
        /// Builds the component to Mapping dictionary. Before building it the methods make sure that the dictionary is empty
        /// </summary>
        private void BuildMappings()
        {
            // do some safety work
            bool measureDimensionMapped = false;
            IComponentMapping frequencyMapping = null;

            // fill the dictionaries and the fields
            foreach (MappingEntity mapping in this._mappingSet.Mappings)
            {
                if (this.IsTimeDimensionMapping(mapping))
                {
                    // find the mapping that contains the timedimension
                    this._timeMapping = mapping;
                    this._componentMapping.Add(mapping.Components[0], mapping);
                }
                else
                {
                    foreach (ComponentEntity component in mapping.Components)
                    {
                        this._componentMapping.Add(component, mapping);

                        IComponentMapping componentMapping = Sri.MappingStoreRetrieval.Engine.Mapping.ComponentMapping.CreateComponentMapping(component, mapping);

                        //// TODO REMOVE this._componentMappingType.Add(component, componentMapping);
                        this._componentIdMap.Add(component.Id, componentMapping);

                        switch (component.ComponentType)
                        {
                            case SdmxComponentType.Dimension:
                                if (component.MeasureDimension)
                                {
                                    measureDimensionMapped = true;
                                }

                                if (component.FrequencyDimension)
                                {
                                    frequencyMapping = componentMapping;
                                }

                                if (component.Id.Equals(this._dimensionAtObservation))
                                {
                                    this._dimensionAtObservationMapping = componentMapping;
                                }

                                break;
                            case SdmxComponentType.CrossSectionalMeasure:
                                this._xsMeasureMappings.Add(component.CrossSectionalMeasureCode, mapping);
                                break;
                        }
                    }
                }
            }

            this._componentMappingList = new IComponentMapping[this._componentIdMap.Count];
            this._componentIdMap.Values.CopyTo(this._componentMappingList, 0);
            if (this._timeMapping != null)
            {
                    this._timeTranscoder = TimeDimensionMapping.Create(this._timeMapping, frequencyMapping, this._mappingSet.DataSet.Connection.DBType);
            }

            if (!measureDimensionMapped)
            {
                foreach (ComponentEntity component in this._mappingSet.Dataflow.Dsd.Dimensions)
                {
                    if (component.MeasureDimension)
                    {
                        this.MeasureComponent = component;
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// Create time dimension mapping with transcoding 
        /// </summary>
        /// <param name="mapping">
        ///     The mapping entity<see cref="MappingEntity"/> of the Time Dimension component
        /// </param>
        /// <param name="databaseType">
        ///     The dissemination database vendor. Is needed to generate the correct SQL query where conditions
        /// </param>
        /// <param name="timeTranscoding">
        /// The Mapping Store <c>TIME_TRANSCODING</c> object
        /// </param>
        /// <exception cref="TranscodingException">
        /// Incomplete/Invalid mapping or expression
        /// </exception>
        /// <returns>
        /// An Time Dimension Transcoding object<see cref="ITimeDimension"/>
        /// </returns>
        private static ITimeDimensionMapping CreateTranscodedTimeDimensionMapping(MappingEntity mapping, string databaseType, TimeTranscodingEntity timeTranscoding)
        {
            ITimeDimensionMapping timeDimensionTranscoding;
            TimeExpressionEntity expr = TimeExpressionEntity.CreateExpression(timeTranscoding);

            if (!expr.IsDateTime)
            {
                if (!expr.OneColumnMapping)
                {
                    timeDimensionTranscoding = new TimeDimension2Column(mapping, expr, databaseType);
                }
                else
                {
                    if (expr.YearLength != 4)
                    {
                        throw new TranscodingException(ErrorMessages.TimeDimensionYearNo4Digits);
                    }

                    if (expr.Freq != TimeFormatEnumType.Year)
                    {
                        if (expr.PeriodLength <= 0 && expr.YearStart > expr.PeriodStart)
                        {
                            throw new TranscodingException(ErrorMessages.TimeDimensionVariableLenPeriodNotFirst);
                        }

                        if (((expr.YearStart + expr.YearLength) > expr.PeriodStart && expr.YearStart < expr.PeriodStart)
                            ||
                            ((expr.PeriodStart + expr.PeriodLength) > expr.YearStart
                             && expr.YearStart > expr.PeriodStart) || expr.PeriodStart == expr.YearStart)
                        {
                            throw new TranscodingException(ErrorMessages.TimeDimensionYearPeriodOverlap);
                        }
                    }

                    timeDimensionTranscoding = new TimeDimension1Column(mapping, expr, databaseType);
                }
            }
            else
            {
                timeDimensionTranscoding = new TimeDimensionDateType(mapping, expr, databaseType);
            }

            return timeDimensionTranscoding;
        }
 /// <summary>
 /// Returns a value indicating whether the <paramref name="mapping"/> is for a TimeDimension
 /// </summary>
 /// <param name="mapping">
 /// The <see cref="MappingEntity"/> to check 
 /// </param>
 /// <returns>
 /// A value indicating whether the <paramref name="mapping"/> is for a TimeDimension 
 /// </returns>
 private bool IsTimeDimensionMapping(MappingEntity mapping)
 {
     return this._mappingSet.Dataflow.Dsd.TimeDimension != null && mapping.Components.Count == 1
            && mapping.Components[0].SysId == this._mappingSet.Dataflow.Dsd.TimeDimension.SysId;
 }
        /// <summary>
        /// Create the IComponentMapping object for a specific component in a mapping depending on the type of mapping e.g. 1
        ///     DSD component - N local columns e.t.c.
        /// </summary>
        /// <param name="component">
        /// The component entity
        /// </param>
        /// <param name="mapping">
        /// The mapping entity
        /// </param>
        /// <returns>
        /// An IComponentMapping object based on the mapping or null if the mapping is not supported
        /// </returns>
        /// <exception cref="TranscodingException">
        /// Invalid or unsupported mapping
        /// </exception>
        public static IComponentMapping CreateComponentMapping(ComponentEntity component, MappingEntity mapping)
        {
            IComponentMapping componentMapping;
            if (mapping.Components.Count == 1)
            {
                // one component
                switch (mapping.Columns.Count)
                {
                    case 0: // no columns => constant mapping
                        if (mapping.Constant != null)
                        {
                            componentMapping = new ComponentMapping1C();
                        }
                        else
                        {
                            throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNoMappingFormat1, mapping.Components[0]));
                        }

                        break;
                    case 1: // 1 to 1 mapping
                        if (mapping.Transcoding != null)
                        {
                            // with transcoding
                            if (mapping.Transcoding.TranscodingRules.ColumnAsKeyPosition.Count > 0 && mapping.Transcoding.TranscodingRules.ComponentAsKeyPosition.Count > 0)
                            {
                                componentMapping = new ComponentMapping1To1T();
                            }
                            else
                            {
                                // transcoding enabled but no transcoding rules
                                // TODO log a warning
                                componentMapping = new ComponentMapping1To1(); // disable transcoding
                            }
                        }
                        else
                        {
                            // without transcoding
                            componentMapping = new ComponentMapping1To1();
                        }

                        break;
                    default: // N columns where N > 1
                        if (mapping.Transcoding != null)
                        {
                            // transcoding is mandatory
                            if (mapping.Transcoding.TranscodingRules.ColumnAsKeyPosition.Count > 0 && mapping.Transcoding.TranscodingRules.ComponentAsKeyPosition.Count > 0)
                            {
                                // there are transcoding rules
                                componentMapping = new ComponentMapping1N();
                            }
                            else
                            {
                                throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNoTranscodingRulesFormat1, component.Id));
                            }
                        }
                        else
                        {
                            throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNoTranscodingFormat1, component.Id));
                        }

                        break;
                }
            }
            else if (mapping.Columns.Count == 1 && mapping.Components.Count > 1)
            {
                // N components to 1 column mapping 
                if (mapping.Transcoding != null)
                {
                    // transcoding is mandatory
                    if (mapping.Transcoding.TranscodingRules.ColumnAsKeyPosition.Count > 0 && mapping.Transcoding.TranscodingRules.ComponentAsKeyPosition.Count > 0)
                    {
                        // there are transcoding rules
                        componentMapping = new ComponentMappingNto1(mapping.Transcoding.TranscodingRules.ComponentAsKeyPosition[component.SysId]);
                    }
                    else
                    {
                        throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNoTranscodingRulesFormat1, component.Id));
                    }
                }
                else
                {
                    throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNoTranscodingFormat1, component.Id));
                }
            }
            else
            {
                throw new TranscodingException(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ComponentMappingNNMapping, component.Id));
            }

            componentMapping.Mapping = mapping;
            componentMapping.Component = component;
            return componentMapping;
        }