/// <summary>
        /// Constructor that takes a type which implements <see cref="IDataCookerDescriptor"/>.
        /// </summary>
        /// <param name="dataCookerType">Identifies the required data cooker</param>
        public RequiresCookerAttribute(Type dataCookerType)
        {
            Guard.NotNull(dataCookerType, nameof(dataCookerType));

            if (!dataCookerType.IsPublicAndInstantiatableOfType(typeof(IDataCookerDescriptor)))
            {
                throw new ArgumentException($"Cannot instantiate type {dataCookerType} as an {nameof(IDataCookerDescriptor)}.");
            }

            // There must be an empty, public constructor
            var constructor = dataCookerType.GetConstructor(Type.EmptyTypes);

            if (constructor == null || !constructor.IsPublic)
            {
                throw new ArgumentException($"Type {dataCookerType} lacks an empty public constructor.");
            }

            IDataCookerDescriptor cookerDescriptor = null;

            try
            {
                cookerDescriptor = Activator.CreateInstance(dataCookerType) as IDataCookerDescriptor;
            }
            catch (Exception e)
            {
                throw new ArgumentException($"Unable to instantiate type {dataCookerType} as an {nameof(IDataCookerDescriptor)}.", e);
            }

            if (cookerDescriptor == null)
            {
                throw new ArgumentException($"Unable to instantiate type {dataCookerType} as an {nameof(IDataCookerDescriptor)}.");
            }

            this.RequiredDataCookerPath = new DataCookerPath(cookerDescriptor.Path);
        }
Esempio n. 2
0
 internal DataCookerSchedulingNode(
     IDataCookerDescriptor dataCooker,
     ISourceDataCookerDependencyTypes sourceDataCooker)
 {
     this.DataCooker                 = dataCooker;
     this.CookerDependencies         = sourceDataCooker;
     this.SourceDataCookerDescriptor = this.CookerDependencies;
 }
Esempio n. 3
0
        protected override void ValidateInstance(IDataCookerDescriptor instance)
        {
            base.ValidateInstance(instance);

            if (!StringComparer.Ordinal.Equals(instance.Path.SourceParserId, DataCookerPath.EmptySourceParserId))
            {
                this.AddError($"Unable to create an instance of {this.Type}");
                this.InitialAvailability = DataExtensionAvailability.Error;
            }
        }
        internal void ScheduleDataCookers(IReadOnlyCollection <IDataCookerDescriptor> dataCookers)
        {
            Guard.NotNull(dataCookers, nameof(dataCookers));

            if (this.scheduled)
            {
                throw new InvalidOperationException(
                          $"{nameof(this.ScheduleDataCookers)} may not be called more than once.");
            }

            this.scheduled = true;

            foreach (var dataCooker in dataCookers)
            {
                if (!StringComparer.Ordinal.Equals(dataCooker.Path.SourceParserId, this.SourceParserId))
                {
                    throw new ArgumentException(
                              $"Data Cooker {dataCooker.Path} does not target source parser {this.SourceParserId}.",
                              nameof(dataCooker));
                }

                if (!(dataCooker is ISourceDataCookerDescriptor))
                {
                    throw new ArgumentException(
                              $"Cooker {dataCooker.Path} is not a source data cooker.",
                              nameof(dataCookers));
                }

                this.dataCookerPathsToDataCookers.Add(dataCooker.Path, dataCooker);
                this.cookersToNodes.Add(dataCooker, DataCookerSchedulingNode.CreateSchedulingNode(dataCooker));
            }

            // Make sure each cooker is scheduled and determine the number of passes, blocks, and cookers
            // per block.
            //
            foreach (var kvp in this.cookersToNodes)
            {
                IDataCookerDescriptor dataCooker = kvp.Key;
                var sourceCooker   = dataCooker as ISourceDataCookerDescriptor;
                var schedulingNode = kvp.Value;

                Debug.Assert(!(sourceCooker is null));
                Debug.Assert(schedulingNode.Status != SchedulingStatus.Scheduling);

                schedulingNode.Schedule(this, null);
            }

            this.DataCookersBySourcePass = new List <List <IDataCookerDescriptor> >(this.passes.Count);
            foreach (var scheduledPass in this.passes)
            {
                this.DataCookersBySourcePass.Add(scheduledPass.GetCookers());
            }
        }
        protected virtual void ValidateInstance(IDataCookerDescriptor instance)
        {
            // Create an instance just to pull out the descriptor without saving any references to it.
            if (instance is null)
            {
                this.AddError($"Unable to create an instance of {this.Type}");
                this.InitialAvailability = DataExtensionAvailability.Error;
                return;
            }

            if (string.IsNullOrWhiteSpace(instance.Path.DataCookerId))
            {
                this.AddError("A data cooker Id may not be empty or null.");
                this.InitialAvailability = DataExtensionAvailability.Error;
            }
        }
Esempio n. 6
0
        internal static DataCookerSchedulingNode CreateSchedulingNode(IDataCookerDescriptor dataCooker)
        {
            Guard.NotNull(dataCooker, nameof(dataCooker));

            if (!(dataCooker is ISourceDataCookerDependencyTypes sourceDataCooker))
            {
                throw new ArgumentException(
                          $"Data Cooker {dataCooker.Path} does not support " +
                          $"{nameof(ISourceDataCookerDependencyTypes)}.",
                          nameof(dataCooker));
            }

            if (sourceDataCooker.DataProductionStrategy == DataProductionStrategy.AsRequired)
            {
                return(new AsRequiredCookerSchedulingNode(dataCooker, sourceDataCooker));
            }

            return(new DataCookerSchedulingNode(dataCooker, sourceDataCooker));
        }
        protected void InitializeDescriptorData(IDataCookerDescriptor descriptor)
        {
            Guard.NotNull(descriptor, nameof(descriptor));

            this.Path        = descriptor.Path;
            this.Description = descriptor.Description;

            if (this.IsSourceDataCooker)
            {
                if (string.IsNullOrEmpty(descriptor.Path.SourceParserId))
                {
                    this.AddError($"A source data cooker's source Id must not be {nameof(DataCookerPath.EmptySourceParserId)}.");
                    this.InitialAvailability = DataExtensionAvailability.Error;
                }
            }
            else
            {
                if (descriptor.Path.SourceParserId != DataCookerPath.EmptySourceParserId)
                {
                    this.AddError($"A composite data cooker's source Id must be {nameof(DataCookerPath.EmptySourceParserId)}.");
                    this.InitialAvailability = DataExtensionAvailability.Error;
                }
            }

            if (descriptor is IDataCookerDependent cookerRequirements)
            {
                foreach (var dataCookerPath in cookerRequirements.RequiredDataCookers)
                {
                    this.AddRequiredDataCooker(dataCookerPath);
                }
            }

            if (descriptor is IDataProcessorDependent processorRequirements)
            {
                foreach (var dataProcessorId in processorRequirements.RequiredDataProcessors)
                {
                    this.AddRequiredDataProcessor(dataProcessorId);
                }
            }
        }
Esempio n. 8
0
 internal AsRequiredCookerSchedulingNode(
     IDataCookerDescriptor dataCooker,
     ISourceDataCookerDependencyTypes sourceDataCooker)
     : base(dataCooker, sourceDataCooker)
 {
 }