/// <summary>
 /// Retrieve the structures referenced by <paramref name="queries"/> and populate the
 ///     <paramref name="mutableObjects"/>
 /// </summary>
 /// <param name="retrievalManager">
 ///     The retrieval manager.
 /// </param>
 /// <param name="mutableObjects">
 ///     The mutable objects.
 /// </param>
 /// <param name="queries">
 ///     The queries.
 /// </param>
 /// <param name="returnLatest">
 ///     The return Latest.
 /// </param>
 /// <param name="returnStub">
 ///     The return Stub.
 /// </param>
 /// <param name="allowedDataflows">
 ///     The allowed Dataflows.
 /// </param>
 /// <param name="crossReferenceMutableRetrievalManager">
 ///     The cross reference mutable retrieval manager.
 /// </param>
 protected virtual void PopulateMutables(IAuthAdvancedSdmxMutableObjectRetrievalManager retrievalManager, IMutableObjects mutableObjects, IList<IStructureReference> queries, bool returnLatest, StructureQueryDetailEnumType returnStub, IList<IMaintainableRefObject> allowedDataflows, IAuthCrossReferenceMutableRetrievalManager crossReferenceMutableRetrievalManager)
 {
     //// changes here might also apply to AuthAdvancedMutableStructureSearchManagerBase 
     for (int i = 0; i < queries.Count; i++)
     {
         var structureReference = queries[i];
         IRestStructureQuery restStructureQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(returnStub), StructureReferenceDetail.GetFromEnum(StructureReferenceDetailEnumType.None), null, structureReference, returnLatest);
         var complexStructureQuery = _complexQueryBuilder.Build(restStructureQuery);
         base.PopulateMutables(retrievalManager, mutableObjects, complexStructureQuery, allowedDataflows, crossReferenceMutableRetrievalManager);
     }
 }
        /// <summary>
        /// Retrieve the <paramref name="queries"/> and populate the <paramref name="mutableObjects"/>
        /// </summary>
        /// <param name="retrievalManager">
        ///     The retrieval manager.
        /// </param>
        /// <param name="mutableObjects">
        ///     The mutable objects.
        /// </param>
        /// <param name="queries">
        ///     The structure queries
        /// </param>
        /// <param name="returnLatest">
        ///     Set to <c>true</c> to retrieve the latest; otherwise set to <c>false</c> to retrieve all versions
        /// </param>
        /// <param name="returnStub">
        ///     Set to <c>true</c> to retrieve artefacts as stubs; otherwise set to <c>false</c> to retrieve full artefacts.
        /// </param>
        /// <param name="allowedDataflows">
        ///     The allowed dataflows.
        /// </param>
        /// <param name="crossReferenceMutableRetrievalManager">
        ///     The cross-reference manager
        /// </param>
        protected override void PopulateMutables(IAuthAdvancedSdmxMutableObjectRetrievalManager retrievalManager, IMutableObjects mutableObjects, IList<IStructureReference> queries, bool returnLatest, StructureQueryDetailEnumType returnStub, IList<IMaintainableRefObject> allowedDataflows, IAuthCrossReferenceMutableRetrievalManager crossReferenceMutableRetrievalManager)
        {
            var dataflowLessQueries = new List<IStructureReference>();
            var dataflowQueries = new List<IStructureReference>();
            foreach (var query in queries)
            {
                if (query.MaintainableStructureEnumType.EnumType == SdmxStructureEnumType.Dataflow)
                {
                    dataflowQueries.Add(query);
                }
                else
                {
                    dataflowLessQueries.Add(query);
                }
            }

            base.PopulateMutables(retrievalManager, mutableObjects, dataflowLessQueries, returnLatest, returnStub, allowedDataflows, crossReferenceMutableRetrievalManager);
            
            // get the latest for dataflows to emulate the intermediate SR behavior.
            base.PopulateMutables(retrievalManager, mutableObjects, dataflowQueries, true, returnStub, allowedDataflows, crossReferenceMutableRetrievalManager);
            if (queries.NeedsCategorisation())
            {
                _log.Info("SDMX v2.0 structure search manager used. Trying to retrieve categorisations all dataflows and categorisations.");
                IMutableObjects objects = new MutableObjectsImpl(mutableObjects.Dataflows);
                objects.AddIdentifiables(mutableObjects.CategorySchemes);

                // get categorisations
                IResolverFactory factory = new ResolverFactory();
                var resolver = factory.GetResolver(StructureReferenceDetail.GetFromEnum(StructureReferenceDetailEnumType.Parents), crossReferenceMutableRetrievalManager);
                resolver.ResolveReferences(objects, returnStub == StructureQueryDetailEnumType.AllStubs, allowedDataflows);

                // add them to mutable objects
                mutableObjects.AddIdentifiables(objects.Categorisations);
            }
        }
        /// <summary>
        /// Retrieve the <paramref name="queries"/> and populate the <paramref name="mutableObjects"/>
        /// </summary>
        /// <param name="retrievalManager">
        ///     The retrieval manager.
        /// </param>
        /// <param name="mutableObjects">
        ///     The mutable objects.
        /// </param>
        /// <param name="queries">
        ///     The structure queries
        /// </param>
        /// <param name="returnLatest">
        ///     Set to <c>true</c> to retrieve the latest; otherwise set to <c>false</c> to retrieve all versions
        /// </param>
        /// <param name="returnStub">
        ///     Set to <c>true</c> to retrieve artefacts as stubs; otherwise set to <c>false</c> to retrieve full artefacts.
        /// </param>
        /// <param name="allowedDataflows">
        ///     The allowed dataflows.
        /// </param>
        /// <param name="crossReferenceMutableRetrievalManager">
        ///     The cross-reference manager
        /// </param>
        protected override void PopulateMutables(IAuthAdvancedSdmxMutableObjectRetrievalManager retrievalManager, IMutableObjects mutableObjects, IList<IStructureReference> queries, bool returnLatest, StructureQueryDetailEnumType returnStub, IList<IMaintainableRefObject> allowedDataflows, IAuthCrossReferenceMutableRetrievalManager crossReferenceMutableRetrievalManager)
        {
            try
            {
                // try get the codelist reference
                IMaintainableRefObject codelistReference =
                    queries.Where(structureReference => structureReference.TargetReference.EnumType == SdmxStructureEnumType.CodeList)
                        .Select(structureReference => structureReference.MaintainableReference)
                        .FirstOrDefault();

                // try get the dataflow ref
                var dataflowRef = queries.FirstOrDefault(structureReference => structureReference.TargetReference.EnumType == SdmxStructureEnumType.Dataflow) as IConstrainableStructureReference;

                // check if it is special
                if (codelistReference != null && dataflowRef != null && dataflowRef.ConstraintObject != null && queries.Count == 2)
                {
                    // get the dataflow
                    base.PopulateMutables(
                        retrievalManager,
                        mutableObjects,
                        new IStructureReference[] { dataflowRef },
                        returnLatest,
                        returnStub,
                        allowedDataflows,
                        crossReferenceMutableRetrievalManager);

                    // get the partial codelist
                    StructureRetrievalInfo structureRetrievalInfo = _structureRetrievalInfoBuilder.Build(dataflowRef, this._connectionStringSettings, allowedDataflows);
                    if (!ProcessReference(structureRetrievalInfo, codelistReference, mutableObjects))
                    {
                        string message = string.Format(CultureInfo.InvariantCulture, "No codes found for {0}", codelistReference);
                        _logger.Error(message);
                        throw new SdmxNoResultsException(message);
                    }
                }
                else
                {
                    // not special requests
                    base.PopulateMutables(retrievalManager, mutableObjects, queries, returnLatest, returnStub, allowedDataflows, crossReferenceMutableRetrievalManager);
                }
            }
            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 SdmxInternalServerException(e.Message);
                }
            }
            catch (DbException e)
            {
                string mesage = "Mapping Store connection error." + e.Message;
                _logger.Error(mesage, e);
                throw new SdmxInternalServerException(mesage);
            }
            catch (Exception e)
            {
                string mesage = e.Message;
                _logger.Error(mesage, e);
                throw new SdmxInternalServerException(mesage);
            }
        }
        /// <summary>
        /// Retrieve the structures referenced by <paramref name="queries"/> and populate the
        ///     <paramref name="mutableObjects"/>
        /// </summary>
        /// <param name="mutableObjects">
        ///     The mutable objects.
        /// </param>
        /// <param name="queries">
        ///     The queries.
        /// </param>
        /// <param name="returnLatest">
        ///     The return Latest.
        /// </param>
        /// <param name="returnStub">
        ///     The return Stub.
        /// </param>
        /// <param name="allowedDataflows">
        ///     The allowed Dataflows.
        /// </param>
        protected virtual void PopulateMutables(IMutableObjects mutableObjects, IList<IStructureReference> queries, bool returnLatest, StructureQueryDetailEnumType returnStub, IList<IMaintainableRefObject> allowedDataflows)
        {
            var cachedRetrievalManager = this._advancedMutableRetrievalManagerFactory.GetRetrievalManager(this._retrievalAdvancedManager);

            var crossReferenceMutableRetrievalManager = this._crossReferenceManager.GetCrossRetrievalManager(this._database, cachedRetrievalManager);
            PopulateMutables(cachedRetrievalManager, mutableObjects, queries, returnLatest, returnStub, allowedDataflows, crossReferenceMutableRetrievalManager);
        }
        public void TestGetMaintainables(
            SdmxStructureEnumType structureEnumType, 
            StructureQueryDetailEnumType detail, 
            StructureReferenceDetailEnumType refDetailEnum, 
            SdmxStructureEnumType specificStructure)
        {
            var mutableSearchManager = this.GetMutableSearchManager(this._connectionString);
            var refDetail = StructureReferenceDetail.GetFromEnum(refDetailEnum);

            var sdmxStructureType = SdmxStructureType.GetFromEnum(specificStructure == SdmxStructureEnumType.HierarchicalCodelist && structureEnumType == SdmxStructureEnumType.CodeList ? SdmxStructureEnumType.HierarchicalCodelist : SdmxStructureEnumType.Categorisation);
            IStructureReference reference = new StructureReferenceImpl(new MaintainableRefObjectImpl(), sdmxStructureType);

            SdmxStructureType structureType = SdmxStructureType.GetFromEnum(structureEnumType);
            IRestStructureQuery query = new RESTStructureQueryCore(
                StructureQueryDetail.GetFromEnum(StructureQueryDetailEnumType.Full),
                StructureReferenceDetail.GetFromEnum(StructureReferenceDetailEnumType.Specific),
                structureType,
                reference,
                false);
            var allObjects = mutableSearchManager.GetMaintainables(query).GetMaintainables(structureType);
            var referenceLevel = StructureReferenceDetail.GetFromEnum(refDetailEnum);

            _log.DebugFormat(CultureInfo.InvariantCulture, "Structure type: {0}, Detail: {1}, Reference : {2}", structureType, detail, refDetail);
            foreach (var maintainableMutableObject in allObjects)
            {
                if ("MA".Equals(maintainableMutableObject.AgencyId))
                {
                    continue;
                }

                var structureReference = _fromMutable.Build(maintainableMutableObject);
                _log.DebugFormat(CultureInfo.InvariantCulture, "Checking maintainable : {0}", structureReference);
                var mockQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(detail), referenceLevel, SdmxStructureType.GetFromEnum(specificStructure), structureReference, false);
                switch (refDetail.EnumType)
                {
                    case StructureReferenceDetailEnumType.Null:
                        break;
                    case StructureReferenceDetailEnumType.None:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            Assert.IsTrue(mutableObject.GetMaintainables(structureType).All(o => o.StructureType.EnumType == structureType.EnumType));
                        }

                        break;
                    case StructureReferenceDetailEnumType.Parents:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            ValidateParents(mutableObject, structureType, detail != StructureQueryDetailEnumType.Full, structureReference);
                        }

                        break;
                    case StructureReferenceDetailEnumType.ParentsSiblings:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            ValidateParentsAndSiblings(mutableObject, structureType, detail != StructureQueryDetailEnumType.Full);
                        }

                        break;
                    case StructureReferenceDetailEnumType.Children:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            ValidateChildren(mutableObject, structureType, detail != StructureQueryDetailEnumType.Full);
                        }

                        break;
                    case StructureReferenceDetailEnumType.Descendants:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            ValidateDescendants(mutableObject, structureType, detail != StructureQueryDetailEnumType.Full);
                        }

                        break;
                    case StructureReferenceDetailEnumType.All:
                        {
                            var mutableObject = GetMutables(mutableSearchManager, mockQuery, maintainableMutableObject);
                            ValidateAll(mutableObject, structureType, detail != StructureQueryDetailEnumType.Full);
                        }

                        break;
                    case StructureReferenceDetailEnumType.Specific:
                        {
                            if (specificStructure != SdmxStructureEnumType.Categorisation || detail == StructureQueryDetailEnumType.Full)
                            {
                                var specificStructureReference = SdmxStructureType.GetFromEnum(specificStructure);
                                var specificQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(detail), referenceLevel, specificStructureReference, structureReference, false);
                                var mutablesWithSpecific = GetMutables(mutableSearchManager, specificQuery, maintainableMutableObject);
                                ValidateSpecific(mutablesWithSpecific, structureType, detail != StructureQueryDetailEnumType.Full, specificStructureReference, structureReference);
                            }
                        }

                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }
        public void TestGetMaintainablesAuthResult(SdmxStructureEnumType structureEnumType, StructureQueryDetailEnumType detail, StructureReferenceDetailEnumType refDetailEnum)
        {
            var mutableSearchManager = this.GetAuthMutableSearchManager(this._connectionString);
            var refDetail = StructureReferenceDetail.GetFromEnum(refDetailEnum);
            var structureType = SdmxStructureType.GetFromEnum(structureEnumType);
            IStructureReference reference = new StructureReferenceImpl(new MaintainableRefObjectImpl(), structureType);
            switch (structureType.EnumType)
            {
                case SdmxStructureEnumType.Dataflow:
                case SdmxStructureEnumType.Dsd:
                    var allowedDataflows = (from x in this._fullRetrievalManager.GetMutableDataflowObjects(new MaintainableRefObjectImpl(), false, false) select _fromMutable.Build(x).MaintainableReference).ToArray();

                    var list = this._fullRetrievalManager.GetMutableMaintainables(reference, false, false);
                    var queryMetadataMock = new Mock<IStructureQueryMetadata>();
                    queryMetadataMock.Setup(query => query.IsReturnLatest).Returns(false);
                    queryMetadataMock.Setup(query => query.SpecificStructureReference).Returns((SdmxStructureType)null);
                    queryMetadataMock.Setup(query => query.StructureReferenceDetail).Returns(refDetail);
                    queryMetadataMock.Setup(query => query.StructureQueryDetail).Returns(StructureQueryDetail.GetFromEnum(detail));

                    var mockQuery = new Mock<IRestStructureQuery>();
                    mockQuery.Setup(query => query.StructureReference).Returns(reference);
                    mockQuery.Setup(query => query.StructureQueryMetadata).Returns(() => queryMetadataMock.Object);
                    _log.DebugFormat(CultureInfo.InvariantCulture, "Structure type: {0}, Detail: {1}, Reference : {2}", structureType, detail, refDetail);
                    foreach (var maintainableMutableObject in list)
                    {
                        switch (refDetail.EnumType)
                        {
                            case StructureReferenceDetailEnumType.Null:
                                break;
                            case StructureReferenceDetailEnumType.None:
                                {
                                    var mutableObject = mutableSearchManager.GetMaintainables(mockQuery.Object, allowedDataflows);
                                    Assert.IsNotNull(mutableObject, _fromMutable.Build(maintainableMutableObject).ToString());
                                    Assert.IsNotEmpty(mutableObject.AllMaintainables, _fromMutable.Build(maintainableMutableObject).ToString());
                                }

                                break;
                            case StructureReferenceDetailEnumType.Parents:
                                {
                                    var mutableObject = mutableSearchManager.GetMaintainables(mockQuery.Object, allowedDataflows);
                                    Assert.IsNotNull(mutableObject, _fromMutable.Build(maintainableMutableObject).ToString());
                                    Assert.IsNotEmpty(mutableObject.AllMaintainables, _fromMutable.Build(maintainableMutableObject).ToString());
                                }

                                break;
                            case StructureReferenceDetailEnumType.ParentsSiblings:
                                break;
                            case StructureReferenceDetailEnumType.Children:
                                {
                                    var mutableObject = mutableSearchManager.GetMaintainables(mockQuery.Object, allowedDataflows);
                                    Assert.IsNotNull(mutableObject, _fromMutable.Build(maintainableMutableObject).ToString());
                                    Assert.IsNotEmpty(mutableObject.AllMaintainables, _fromMutable.Build(maintainableMutableObject).ToString());
                                }

                                break;
                            case StructureReferenceDetailEnumType.Descendants:
                                break;
                            case StructureReferenceDetailEnumType.All:
                                break;
                            case StructureReferenceDetailEnumType.Specific:
                                {
                                    queryMetadataMock.Setup(query => query.StructureReferenceDetail).Returns(StructureReferenceDetail.GetFromEnum(StructureReferenceDetailEnumType.None));
                                    var mutableObject = mutableSearchManager.GetMaintainables(mockQuery.Object, allowedDataflows);
                                    queryMetadataMock.Setup(query => query.StructureReferenceDetail).Returns(refDetail);
                                    Assert.IsNotNull(mutableObject, _fromMutable.Build(maintainableMutableObject).ToString());
                                    Assert.IsNotEmpty(mutableObject.AllMaintainables, _fromMutable.Build(maintainableMutableObject).ToString());
                                }

                                break;
                            default:
                                throw new ArgumentOutOfRangeException();
                        }
                    }

                    break;
            }
        }
 private string  GetStructureQueryFormat(IStructureReference dataflowRef, string version,StructureQueryDetailEnumType structureQueryDetail, StructureReferenceDetailEnumType structureReference )
 {
     IStructureQueryFormat<string> structureQueryFormat = new RestQueryFormat();
     IStructureQueryFactory factory = new RestStructureQueryFactory();
     IStructureQueryBuilderManager structureQueryBuilderManager = new StructureQueryBuilderManager(factory);
     bool returnLatest = version == null;
     SdmxStructureType specificStructureReference = structureReference == StructureReferenceDetailEnumType.Specific? SdmxStructureType.GetFromEnum(SdmxStructureEnumType.CodeList) : null;
     IRestStructureQuery structureQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(structureQueryDetail), StructureReferenceDetail.GetFromEnum(structureReference), specificStructureReference, dataflowRef, returnLatest);
     string request = structureQueryBuilderManager.BuildStructureQuery(structureQuery, structureQueryFormat);
     return request;
 }
        public void TestRestStructureQueryIsMaintainable(string agency, string id, string version, StructureQueryDetailEnumType structureQueryDetail, StructureReferenceDetailEnumType structureReferenceDetail)
        {

            var dataflowRef = new StructureReferenceImpl(SdmxStructureType.GetFromEnum(SdmxStructureEnumType.Dataflow))
            {
                MaintainableId = id,
                AgencyId = agency,
                Version = version,
            };

            bool returnLatest = version == null;
            IRestStructureQuery structureQuery;
            
            Assert.Throws<SdmxSemmanticException>(() => structureQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(structureQueryDetail), StructureReferenceDetail.GetFromEnum(structureReferenceDetail), SdmxStructureType.GetFromEnum(SdmxStructureEnumType.Code), dataflowRef, returnLatest));
            Assert.Throws<SdmxSemmanticException>(() => structureQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(structureQueryDetail), StructureReferenceDetail.GetFromEnum(structureReferenceDetail), SdmxStructureType.GetFromEnum(SdmxStructureEnumType.Category), dataflowRef, returnLatest));
            Assert.Throws<SdmxSemmanticException>(() => structureQuery = new RESTStructureQueryCore(StructureQueryDetail.GetFromEnum(structureQueryDetail), StructureReferenceDetail.GetFromEnum(structureReferenceDetail), SdmxStructureType.GetFromEnum(SdmxStructureEnumType.Dimension), dataflowRef, returnLatest));

        }
        public void TestRestStructureQueryExpectedResultTest2(string agency, string id, string version, string expectedResult, StructureQueryDetailEnumType structureQueryDetail, StructureReferenceDetailEnumType structureReferenceDetail)
        {

            var dataflowRef = new StructureReferenceImpl(SdmxStructureType.GetFromEnum(SdmxStructureEnumType.Dataflow))
            {
                MaintainableId = id,
                AgencyId = agency,
                Version = version,
            };

            string request = GetStructureQueryFormat(dataflowRef, version, structureQueryDetail, structureReferenceDetail);
            Assert.IsNotNull(request);
            Assert.AreEqual(request, expectedResult);

        }