/// <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); }
internal DataCookerSchedulingNode( IDataCookerDescriptor dataCooker, ISourceDataCookerDependencyTypes sourceDataCooker) { this.DataCooker = dataCooker; this.CookerDependencies = sourceDataCooker; this.SourceDataCookerDescriptor = this.CookerDependencies; }
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; } }
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); } } }
internal AsRequiredCookerSchedulingNode( IDataCookerDescriptor dataCooker, ISourceDataCookerDependencyTypes sourceDataCooker) : base(dataCooker, sourceDataCooker) { }