/// <summary>
        ///     A composite cooker has access to source data cookers, as well as other composite data cookers.
        /// </summary>
        /// <param name="dataCookerPath">
        ///     Identifies the composite data cooker.
        /// </param>
        /// <returns>
        ///     A set of data uniquely tailored to this composite data cooker.
        /// </returns>
        public IDataExtensionRetrieval CreateDataRetrievalForCompositeDataCooker(
            DataCookerPath dataCookerPath)
        {
            var filteredData = this.dataRetrievalCache.GetCompositeDataCookerFilteredData(dataCookerPath);

            if (filteredData != null)
            {
                return(filteredData);
            }

            var compositeDataCookerReference = this.DataExtensionRepository.GetCompositeDataCookerReference(dataCookerPath);

            if (compositeDataCookerReference == null)
            {
                throw new ArgumentException("Data retrieval requested for data cooker not found in repository.");
            }

            if (compositeDataCookerReference.Availability != DataExtensionAvailability.Available)
            {
                throw new ArgumentException("Data retrieval requested for data cooker that is not available.");
            }

            filteredData = new FilteredDataRetrieval(this, compositeDataCookerReference.DependencyReferences);

            this.dataRetrievalCache.AddCompositeDataCookerFilteredData(dataCookerPath, filteredData);

            return(filteredData);
        }
        /// <summary>
        ///     A data processor has access to source data cookers, composite data cookers, as well as other
        ///     data processors.
        /// </summary>
        /// <param name="dataProcessorId">
        ///     Identifies the data processor.
        /// </param>
        /// <returns>
        ///     A set of data uniquely tailored to this data processor.
        /// </returns>
        public IDataExtensionRetrieval CreateDataRetrievalForDataProcessor(
            DataProcessorId dataProcessorId)
        {
            var filteredData = this.dataRetrievalCache.GetDataProcessorFilteredData(dataProcessorId);

            if (filteredData != null)
            {
                return(filteredData);
            }

            var dataProcessorReference = this.DataExtensionRepository.GetDataProcessorReference(dataProcessorId);

            if (dataProcessorReference == null)
            {
                throw new ArgumentException("Data retrieval requested for data processor not found in repository.");
            }

            if (dataProcessorReference.Availability != DataExtensionAvailability.Available)
            {
                throw new ArgumentException("Data retrieval requested for data processor that is not available.");
            }

            filteredData = new FilteredDataRetrieval(this, dataProcessorReference.DependencyReferences);

            this.dataRetrievalCache.AddDataProcessorFilteredData(dataProcessorId, filteredData);

            return(filteredData);
        }
        /// <summary>
        ///     A table has access to source data cookers, composite data cookers, and data processors.
        /// </summary>
        /// <param name="tableExtensionReference">
        ///     Reference to a table data extension.
        /// </param>
        /// <returns>
        ///     A set of data uniquely tailored to this table.
        /// </returns>
        public IDataExtensionRetrieval CreateDataRetrievalForTable(
            ITableExtensionReference tableExtensionReference)
        {
            Guard.NotNull(tableExtensionReference, nameof(tableExtensionReference));

            if (tableExtensionReference.Availability != DataExtensionAvailability.Available)
            {
                throw new ArgumentException("Data retrieval requested for table that is not available.");
            }

            var filteredData = new FilteredDataRetrieval(this, tableExtensionReference.DependencyReferences);

            return(filteredData);
        }