/// <summary>
        /// Build a <see cref="StructureRetrievalInfo"/> from the specified parameters
        /// </summary>
        /// <param name="dataflow">
        /// The dataflow to get the available data for 
        /// </param>
        /// <param name="connectionStringSettings">
        /// The Mapping Store connection string settings 
        /// </param>
        /// <param name="allowedDataflows">
        /// The collection of allowed dataflows 
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// connectionStringSettings is null
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// dataflow is null
        /// </exception>
        /// <exception cref="StructureRetrieverException">
        /// Parsing error or mapping store exception error
        /// </exception>
        /// <returns>
        /// a <see cref="StructureRetrievalInfo"/> from the specified parameters 
        /// </returns>
        public StructureRetrievalInfo Build(
            IConstrainableStructureReference dataflow,
            ConnectionStringSettings connectionStringSettings,
            IList<IMaintainableRefObject> allowedDataflows)
        {
            if (connectionStringSettings == null)
            {
                throw new ArgumentNullException("connectionStringSettings");
            }

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

            var info = new StructureRetrievalInfo(_logger, allowedDataflows, connectionStringSettings);
            try
            {
                info.MappingSet = MappingSetRetriever.GetMappingSet(
                info.ConnectionStringSettings,
                dataflow.MaintainableReference.MaintainableId,
                dataflow.MaintainableReference.Version,
                dataflow.MaintainableReference.AgencyId,
                info.AllowedDataflows);
                if (info.MappingSet != null)
                {
                    ParserDataflowRef(dataflow, info);
                    Initialize(info);
                }
            }
            catch (SdmxException)
            {
                throw;
            }
            catch (StructureRetrieverException e)
            {
                _logger.Error(e.Message, e);
                switch (e.ErrorType)
                {
                    case StructureRetrieverErrorTypes.ParsingError:
                        throw new SdmxSyntaxException(e, ExceptionCode.XmlParseException);
                    case StructureRetrieverErrorTypes.MissingStructure:
                    case StructureRetrieverErrorTypes.MissingStructureRef:
                        throw new SdmxNoResultsException(e.Message);
                    default:
                        throw new SdmxException(e, SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError), e.Message);
                }
            }
            catch (DbException e)
            {
                string mesage = "Mapping Store connection error." + e.Message;
                _logger.Error(mesage);
                _logger.Error(e.ToString());
                throw new SdmxException(e, SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError), mesage);
            }
            catch (Exception e)
            {
                string mesage = string.Format(
                    CultureInfo.CurrentCulture,
                    ErrorMessages.ErrorRetrievingMappingSetFormat4,
                    dataflow.MaintainableReference.AgencyId,
                    dataflow.MaintainableReference.MaintainableId,
                    dataflow.MaintainableReference.Version,
                    e.Message);
                _logger.Error(mesage);
                _logger.Error(e.ToString());
                throw new SdmxException(e, SdmxErrorCode.GetFromEnum(SdmxErrorCodeEnumType.InternalServerError), mesage);
            }

            return info;
        }
        /// <summary>
        /// Parse the specified DataflowRefBean object and populate the <see cref="StructureRetrievalInfo.RequestedComponent"/> and <see cref="StructureRetrievalInfo.Criteria"/> fields
        /// </summary>
        /// <param name="d">
        /// The DataflowRefBean to parse 
        /// </param>
        /// <param name="info">
        /// The current structure retrieval state 
        /// </param>
        private static void ParserDataflowRef(IConstrainableStructureReference d, StructureRetrievalInfo info)
        {
            if (d.ConstraintObject != null && d.ConstraintObject.IncludedCubeRegion != null)
            {
                foreach (IKeyValues member in d.ConstraintObject.IncludedCubeRegion.KeyValues)
                {
                    if (member.Values.Count == 0 || (member.Values.Count == 1 && SpecialValues.DummyMemberValue.Equals(member.Values[0])))
                    {
                        info.RequestedComponent = GetRequestedComponentId(info.MappingSet.Dataflow.Dsd, member.Id);
                    }
                    else
                    {
                        IKeyValuesMutable normalizedMember = new KeyValuesMutableImpl(member) { Id = GetRequestedComponentId(info.MappingSet.Dataflow.Dsd, member.Id) };
                        var keyValuesCore = new KeyValuesCore(normalizedMember, member.Parent);
                        info.Criteria.Add(keyValuesCore);
                    }
                }

                info.ReferencePeriod = d.ConstraintObject.MutableInstance.ReferencePeriod;
            }
        }