/// <summary>
 /// Retrieve the structures referenced by <paramref name="structureQuery" /> and populate the
 /// <paramref name="mutableObjects" />
 /// </summary>
 /// <param name="retrievalManager">The retrieval manager.</param>
 /// <param name="mutableObjects">The mutable objects.</param>
 /// <param name="structureQuery">The structure query.</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,
     IComplexStructureQuery structureQuery,
     IList<IMaintainableRefObject> allowedDataflows,
     IAuthCrossReferenceMutableRetrievalManager crossReferenceMutableRetrievalManager)
 {
     //// changes here might also apply to AuthMutableStructureSearchManagerBase and/or AuthStructureRetrieverV21 
     var complexStructureQueryDetail = structureQuery.StructureQueryMetadata != null ? structureQuery.StructureQueryMetadata.StructureQueryDetail : ComplexStructureQueryDetail.GetFromEnum(ComplexStructureQueryDetailEnumType.Full);
     mutableObjects.AddIdentifiables(retrievalManager.GetMutableMaintainables(structureQuery.StructureReference, complexStructureQueryDetail, allowedDataflows));
 }
        /// <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>
        /// Resolve references of the specified <paramref name="mutableObjects"/> using the specified
        ///     <paramref name="getReference"/>
        /// </summary>
        /// <param name="mutableObjects">
        /// The mutable objects.
        /// </param>
        /// <param name="getReference">
        /// The method to retrieve cross reference
        /// </param>
        protected internal static void Resolve(IMutableObjects mutableObjects, Func<IMaintainableMutableObject, IList<IMaintainableMutableObject>> getReference)
        {
            var original = new HashSet<IMaintainableMutableObject>(mutableObjects.AllMaintainables);

            int count = 0;
            foreach (IMaintainableMutableObject resolveFor in original)
            {
                IList<IMaintainableMutableObject> referencingStructures = getReference(resolveFor);
                count += referencingStructures.Count;
                mutableObjects.AddIdentifiables(referencingStructures);
            }

            _log.InfoFormat(CultureInfo.InvariantCulture, "Found {0} references.", count);
        }