/// <summary>
        /// Returns a set of structures that are directly referenced from this provision
        /// </summary>
        /// <param name="provision">
        /// - the provision to resolve the references for 
        /// </param>
        /// <param name="structRetrievalManager">
        /// - must not be null as this will be used to resolve the references 
        /// </param>
        /// <returns>
        ///  a set of structures that are directly referenced from this provision
        /// </returns>
        public virtual ISet<IIdentifiableObject> ResolveReferences(
            IProvisionAgreementObject provision, ISdmxRetrievalManager structRetrievalManager)
        {
            if (structRetrievalManager == null)
            {
                throw new ArgumentException("StructureRetrievalManager can not be null");
            }

            this._structureRetrievalManager = structRetrievalManager;

            ISet<IIdentifiableObject> returnSet = new HashSet<IIdentifiableObject>();
            if (provision.StructureUseage != null)
            {
                IMaintainableObject structureUseage = structRetrievalManager.GetMaintainable(provision.StructureUseage);

                if (structureUseage == null)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        provision.StructureUseage.TargetReference.GetType(), 
                        provision.StructureUseage);
                }

                returnSet.Add(structureUseage);
            }

            if (provision.DataproviderRef != null)
            {
                IDataProviderScheme orgScheme =
                    structRetrievalManager.GetDataProviderSchemeBean(provision.DataproviderRef.MaintainableReference);
                if (orgScheme == null)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProviderScheme).ToString(), 
                        provision.DataproviderRef.MaintainableReference);
                }

                var dataProviders = orgScheme.Items;
                if (!ObjectUtil.ValidCollection(dataProviders))
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProvider).ToString(), 
                        provision.DataproviderRef);
                }

                bool found = false;

                /* foreach */
                foreach (IDataProvider dataProvider in dataProviders)
                {
                    if (dataProvider.Id.Equals(provision.DataproviderRef.ChildReference.Id))
                    {
                        found = true;
                        returnSet.Add(orgScheme);
                        break;
                    }
                }

                if (!found)
                {
                    throw new ReferenceException(
                        ExceptionCode.ReferenceErrorUnresolvable, 
                        SdmxStructureType.GetFromEnum(SdmxStructureEnumType.DataProvider).ToString(), 
                        provision.DataproviderRef);
                }
            }

            return returnSet;
        }
        /// <summary>
        /// Resolves a reference from <paramref name="crossReference"/>
        /// </summary>
        /// <param name="crossReference">
        /// The cross reference instance
        /// </param>
        /// <param name="structRetrievalManager">
        /// The structure Retrieval Manager.
        /// </param>
        /// <returns>
        /// a reference from <paramref name="crossReference"/>
        /// </returns>
        public virtual IIdentifiableObject ResolveCrossReference(
            ICrossReference crossReference, ISdmxRetrievalManager structRetrievalManager)
        {
            if (crossReference.TargetReference == SdmxStructureEnumType.Agency)
            {
                return this.ResoveAgency(crossReference.ChildReference.Id);
            }

            var maintainableParent =
                crossReference.ReferencedFrom.GetParent<IMaintainableObject>(typeof(IMaintainableObject), true);
            IStructureReference maintainableReferenceObject;

            if (crossReference.HasChildReference())
            {
                maintainableReferenceObject = new StructureReferenceImpl(
                    crossReference.MaintainableReference, crossReference.MaintainableStructureEnumType);
            }
            else
            {
                maintainableReferenceObject = crossReference;
            }

            IMaintainableObject resolvedMaintainable = this.ResolveMaintainableFromLocalMaps(
                maintainableReferenceObject, maintainableParent);
            if (resolvedMaintainable == null && structRetrievalManager != null)
            {
                // TODO avoid try catch
                try
                {
                    resolvedMaintainable = structRetrievalManager.GetMaintainable(maintainableReferenceObject);
                }
                catch (Exception)
                {
                    throw new ReferenceException(crossReference);
                }
            }

            if (resolvedMaintainable == null)
            {
                throw new ReferenceException(crossReference);
            }

            // Add the maintainable to the local map, so we don't have to go back to the DAO if there is another reference to the same maintainable
            this._maintianables.Add(resolvedMaintainable);
            if (crossReference.HasChildReference())
            {
                string targetUrn = crossReference.TargetUrn;

                /* foreach */
                foreach (IIdentifiableObject currentComposite in resolvedMaintainable.IdentifiableComposites)
                {
                    if (currentComposite.Urn.Equals(targetUrn))
                    {
                        return currentComposite;
                    }
                }
            }
            else
            {
                return resolvedMaintainable;
            }

            throw new ReferenceException(crossReference);
        }