/// <summary> /// Reconfigures this UI (can be called multiple times throughout controls lifetime) to facilitate the population of DemandsInitialization /// properties on an underlying type (e.g. if your collection is ProcessTask and your argument type is ProcessTaskArgument then your underlying type could /// be AnySeparatorFileAttacher or MDFAttacher). Note that while T is IArgumentHost, it also should be tied to one or more interfaces (e.g. IAttacher) and able to host /// any child of that interface of which argumentsAreForUnderlyingType is the currently configured concrete class (e.g. AnySeparatorFileAttacher). /// </summary> /// <param name="parent"></param> /// <param name="argumentsAreForUnderlyingType"></param> /// <param name="catalogueRepository"></param> public void Setup(IArgumentHost parent, Type argumentsAreForUnderlyingType, ICatalogueRepository catalogueRepository) { _parent = parent; _argumentsAreFor = argumentsAreForUnderlyingType; lblTypeUnloadable.Visible = _argumentsAreFor == null; _valueUisFactory = new ArgumentValueUIFactory(); if (_argumentsAreFor != null) { lblClassName.Text = _argumentsAreFor.FullName; } helpIcon1.Left = lblClassName.Right; if (_argumentsAreFor != null) { btnViewSourceCode.Enabled = ViewSourceCodeDialog.GetSourceForFile(_argumentsAreFor.Name + ".cs") != null; btnViewSourceCode.Left = helpIcon1.Right; var summary = catalogueRepository.CommentStore.GetTypeDocumentationIfExists(argumentsAreForUnderlyingType); if (summary != null) { helpIcon1.SetHelpText(_argumentsAreFor.Name, summary); } RefreshArgumentList(); } }
public ExecuteCommandSetArgument(IBasicActivateItems activator, CommandLineObjectPicker picker) : base(activator) { if (picker.Arguments.Count != 3) { SetImpossible($"Wrong number of parameters supplied to command, expected 3 but got {picker.Arguments.Count}"); return; } if (!picker.HasArgumentOfType(0, typeof(IMapsDirectlyToDatabaseTable))) { SetImpossible("First parameter must be an IArgumentHost DatabaseEntity"); return; } _host = picker[0].GetValueForParameterOfType(typeof(IMapsDirectlyToDatabaseTable)) as IArgumentHost; if (_host == null) { SetImpossible("First parameter must be an IArgumentHost"); return; } var args = _host.GetAllArguments(); _arg = args.FirstOrDefault(a => a.Name.Equals(picker[1].RawValue)); if (_arg == null) { SetImpossible($"Could not find argument called '{picker[1].RawValue}' on '{_host}'. Arguments found were {string.Join(",",args.Select(a=>a.Name))}"); return; } Type argType; try { argType = _arg.GetConcreteSystemType(); } catch (Exception e) { SetImpossible("Failed to get system Type of argument:" + e); return; } if (argType == null) { SetImpossible($"Argument '{_arg.Name}' has no listed Type"); return; } if (!picker[2].HasValueOfType(argType)) { SetImpossible($"Provided value '{picker[2].RawValue}' does not match expected Type '{argType.Name}' of argument '{_arg.Name}'"); return; } _value = picker[2].GetValueForParameterOfType(argType); }
public ArgumentValuePipelineUI(ICatalogueRepository catalogueRepository, IArgumentHost parent, Type argumentType) { InitializeComponent(); string typeName = parent.GetClassNameWhoArgumentsAreFor(); _typeOfUnderlyingClass = catalogueRepository.MEF.GetType(typeName); if (_typeOfUnderlyingClass == null) { throw new Exception("Could not identify a Type called " + typeName + " in any loaded assemblies"); } }
/// <summary> /// Synchronizes all arguments (See SyncArgumentsForClass) for the supplied class (<paramref name="underlyingClassTypeForWhichArgumentsWillPopulate"/>) and returns the mapping /// between <see cref="IArgument"/> (which stores the value) and public class property (<see cref="RequiredPropertyInfo"/>) /// </summary> /// <param name="host"></param> /// <param name="underlyingClassTypeForWhichArgumentsWillPopulate"></param> /// <returns></returns> public Dictionary <IArgument, RequiredPropertyInfo> GetDemandDictionary(IArgumentHost host, Type underlyingClassTypeForWhichArgumentsWillPopulate) { var toReturn = new Dictionary <IArgument, RequiredPropertyInfo>(); SyncArgumentsForClass(host, underlyingClassTypeForWhichArgumentsWillPopulate); var required = GetRequiredProperties(underlyingClassTypeForWhichArgumentsWillPopulate); foreach (var key in host.GetAllArguments()) { toReturn.Add(key, required.Single(e => e.Name == key.Name)); } return(toReturn); }
/// <summary> /// Interrogates a class via reflection and enumerates it's properties to find any that have the attribute [DemandsInitialization] /// Each one of these that is found is created as a ProcessTaskArgument of the appropriate Name and PropertyType under the parent ProcessTask /// </summary> /// <returns>Each new ProcessTaskArgument created - note that it will not return existing ones that were already present (and therefore not created)</returns> public IEnumerable <IArgument> CreateArgumentsForClassIfNotExistsGeneric( Type underlyingClassTypeForWhichArgumentsWillPopulate, IArgumentHost host, IArgument[] existingArguments) { var classType = underlyingClassTypeForWhichArgumentsWillPopulate; //get all the properties that must be set on AnySeparatorFileAttacher (Those marked with the attribute DemandsInitialization var propertiesWeHaveToSet = GetRequiredProperties(classType); foreach (var required in propertiesWeHaveToSet) { //theres already a property with the same name if (existingArguments.Any(a => a.Name.Equals(required.Name))) { continue; } //create a new one var argument = host.CreateNewArgument(); //set the type and name argument.SetType(required.PropertyInfo.PropertyType); argument.Name = required.Name; DemandsInitializationAttribute attribute = required.Demand; argument.Description = attribute.Description; if (attribute.DefaultValue != null) { argument.SetValue(attribute.DefaultValue); } var saveable = argument as ISaveable; if (saveable != null) { saveable.SaveToDatabase(); } yield return(argument); } }
/// <summary> /// Reconfigures this UI (can be called multiple times throughout controls lifetime) to facilitate the population of DemandsInitialization /// properties on an underlying type (e.g. if your collection is ProcessTask and your argument type is ProcessTaskArgument then your underlying type could /// be AnySeparatorFileAttacher or MDFAttacher). Note that while T is IArgumentHost, it also should be tied to one or more interfaces (e.g. IAttacher) and able to host /// any child of that interface of which argumentsAreForUnderlyingType is the currently configured concrete class (e.g. AnySeparatorFileAttacher). /// </summary> /// <param name="activator"></param> /// <param name="parent"></param> /// <param name="argumentsAreForUnderlyingType"></param> /// <param name="catalogueRepository"></param> public void Setup(IActivateItems activator, IArgumentHost parent, Type argumentsAreForUnderlyingType, ICatalogueRepository catalogueRepository) { _parent = parent; _argumentsAreFor = argumentsAreForUnderlyingType; _activator = activator; bool typeLoadable = !(_argumentsAreFor == null); lblTypeUnloadable.Visible = !typeLoadable; lblClassName.Visible = typeLoadable; helpIcon1.Visible = typeLoadable; lblArgumentsTitle.Visible = typeLoadable; pArguments.Visible = typeLoadable; lblComponentNotFound.Visible = !pArguments.Visible; _valueUisFactory = new ArgumentValueUIFactory(); if (_argumentsAreFor != null) { lblClassName.Text = UsefulStuff.PascalCaseStringToHumanReadable(_argumentsAreFor.Name); } helpIcon1.Left = lblClassName.Right; if (_argumentsAreFor != null) { var summary = catalogueRepository.CommentStore.GetTypeDocumentationIfExists(argumentsAreForUnderlyingType); if (summary != null) { helpIcon1.SetHelpText(_argumentsAreFor.Name, summary); } else { helpIcon1.ClearHelpText(); } RefreshArgumentList(); } }
/// <summary> /// Creates <see cref="IArgument"/> instances for all demanded properties (See <see cref="GetRequiredProperties"/>) of the given class and deletes any old arguments /// which are no longer required by the class (e.g. due to an API change). /// </summary> /// <param name="host"></param> /// <param name="underlyingClassTypeForWhichArgumentsWillPopulate"></param> public void SyncArgumentsForClass(IArgumentHost host, Type underlyingClassTypeForWhichArgumentsWillPopulate) { if (host.GetClassNameWhoArgumentsAreFor() != underlyingClassTypeForWhichArgumentsWillPopulate.FullName) { throw new ExpectedIdenticalStringsException("IArgumentHost is not currently hosting the Type requested for sync", host.GetClassNameWhoArgumentsAreFor(), underlyingClassTypeForWhichArgumentsWillPopulate.FullName); } var existingArguments = host.GetAllArguments().ToList(); var required = GetRequiredProperties(underlyingClassTypeForWhichArgumentsWillPopulate); //get rid of arguments that are no longer required foreach (var argumentsNotRequired in existingArguments.Where(e => required.All(r => r.Name != e.Name))) { ((IDeleteable)argumentsNotRequired).DeleteInDatabase(); } //create new arguments existingArguments.AddRange(CreateArgumentsForClassIfNotExistsGeneric(underlyingClassTypeForWhichArgumentsWillPopulate, host, existingArguments.ToArray())); //handle mismatches of Type/incompatible values / unloaded Types etc foreach (var r in required) { var existing = existingArguments.SingleOrDefault(e => e.Name == r.Name); if (existing == null) { throw new Exception("Despite creating new Arguments for class '" + underlyingClassTypeForWhichArgumentsWillPopulate + "' we do not have an IArgument called '" + r.Name + "' in the database (host='" + host + "')"); } if (existing.GetSystemType() != r.PropertyInfo.PropertyType) { //user wants to fix the problem existing.SetType(r.PropertyInfo.PropertyType); ((ISaveable)existing).SaveToDatabase(); } } }
public ExecuteCommandSetArgument(IBasicActivateItems activator, IArgumentHost host, IArgument arg, object value) : base(activator) { _host = host; _arg = arg; _value = value; }
private void CreateLine(IArgumentHost parent, IArgument argument, RequiredPropertyInfo required, float maxArgNameWidth) { Label name = new Label(); HelpIcon helpIcon = new HelpIcon(); helpIcon.SetHelpText(GetSystemTypeName(argument.GetSystemType()) ?? "Unrecognised Type:" + argument.Type, required.Demand.Description); helpIcon.Dock = DockStyle.Right; string spaceSeparatedArgumentName = UsefulStuff.PascalCaseStringToHumanReadable(argument.Name); name.Height = helpIcon.Height; name.Text = spaceSeparatedArgumentName; name.TextAlign = ContentAlignment.MiddleLeft; name.Dock = DockStyle.Left; name.Width = (int)maxArgNameWidth + 3 /*padding*/; RAGSmiley ragSmiley = new RAGSmiley(); if (required.Demand.Mandatory && string.IsNullOrWhiteSpace(argument.Value)) { ragSmiley.Fatal(new Exception("Property " + argument.Name + " is Mandatory")); } var args = new ArgumentValueUIArgs(); args.Parent = parent; args.Type = argument.GetSystemType(); args.ContextText = required.Demand.ContextText; try { args.InitialValue = argument.GetValueAsSystemType(); } catch (Exception e) { //add the text value value and report the error if (_valueUisFactory.CanHandleInvalidStringData(args.Type)) { args.InitialValue = argument.Value; } else { args.InitialValue = null; } ragSmiley.Fatal(e); } args.Required = required; args.CatalogueRepository = (ICatalogueRepository)argument.Repository; args.Setter = (v) => { ragSmiley.Reset(); try { argument.SetValue(v); argument.SaveToDatabase(); argument.GetValueAsSystemType(); if (required.Demand.Mandatory && (v == null || string.IsNullOrWhiteSpace(v.ToString()))) { ragSmiley.Fatal(new Exception("Property " + argument.Name + " is Mandatory")); } } catch (Exception ex) { ragSmiley.OnCheckPerformed(new CheckEventArgs("Failed to set property properly", CheckResult.Fail, ex)); } }; args.Fatal = ragSmiley.Fatal; var valueui = (Control)_valueUisFactory.Create(_activator, args); valueui.Dock = DockStyle.Fill; Panel p = new Panel(); p.Height = Math.Max(Math.Max(lblClassName.Height, helpIcon.Height), valueui.Height); p.Dock = DockStyle.Top; name.Location = new Point(0, 0); p.Controls.Add(name); helpIcon.Left = name.Right; p.Controls.Add(helpIcon); ragSmiley.Dock = DockStyle.Right; p.Controls.Add(ragSmiley); p.Controls.Add(valueui); name.Height = p.Height; Label hr = new Label(); hr.AutoSize = false; hr.BorderStyle = BorderStyle.FixedSingle; hr.Height = 1; hr.Dock = DockStyle.Bottom; p.Controls.Add(hr); valueui.BringToFront(); pArguments.Controls.Add(p); }
/// <inheritdoc cref = "CreateArgumentsForClassIfNotExistsGeneric(Type,IArgumentHost,IArgument[])"/> /// <typeparam name="T">A class with one or more Properties marked with DemandsInitialization</typeparam> /// <returns>Each new ProcessTaskArgument created - note that it will not return existing ones that were already present (and therefore not created)</returns> public IEnumerable <IArgument> CreateArgumentsForClassIfNotExistsGeneric <T>(IArgumentHost host, IArgument[] existingArguments) { return(CreateArgumentsForClassIfNotExistsGeneric(typeof(T), host, existingArguments)); }
private void CreateLine(IArgumentHost parent, IArgument argument, RequiredPropertyInfo required) { Label name = new Label(); HelpIcon helpIcon = new HelpIcon(); helpIcon.SetHelpText(GetSystemTypeName(argument.GetSystemType()) ?? "Unrecognised Type:" + argument.Type, required.Demand.Description); helpIcon.Anchor = AnchorStyles.Top | AnchorStyles.Left; string spaceSeparatedArgumentName = UsefulStuff.PascalCaseStringToHumanReadable(argument.Name); name.Height = helpIcon.Height; name.Text = spaceSeparatedArgumentName; name.TextAlign = ContentAlignment.MiddleLeft; name.AutoSize = true; name.Anchor = AnchorStyles.Top | AnchorStyles.Left; RAGSmiley ragSmiley = new RAGSmiley(); if (required.Demand.Mandatory && string.IsNullOrWhiteSpace(argument.Value)) { ragSmiley.Fatal(new Exception("Property " + argument.Name + " is Mandatory")); } var args = new ArgumentValueUIArgs(); args.Parent = parent; args.Type = argument.GetSystemType(); try { args.InitialValue = argument.GetValueAsSystemType(); } catch (Exception e) { //add the text value value and report the error if (_valueUisFactory.CanHandleInvalidStringData(args.Type)) { args.InitialValue = argument.Value; } else { args.InitialValue = null; } ragSmiley.Fatal(e); } args.Required = required; args.CatalogueRepository = (ICatalogueRepository)argument.Repository; args.Setter = (v) => { ragSmiley.Reset(); try { argument.SetValue(v); argument.SaveToDatabase(); argument.GetValueAsSystemType(); if (required.Demand.Mandatory && (v == null || string.IsNullOrWhiteSpace(v.ToString()))) { ragSmiley.Fatal(new Exception("Property " + argument.Name + " is Mandatory")); } } catch (Exception ex) { ragSmiley.OnCheckPerformed(new CheckEventArgs("Failed to set property properly", CheckResult.Fail, ex)); } }; args.Fatal = ragSmiley.Fatal; var valueui = (Control)_valueUisFactory.Create(args); valueui.Anchor = name.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; _valueUIs.Add(valueui); Panel p = new Panel(); p.Height = Math.Max(Math.Max(lblClassName.Height, helpIcon.Height), valueui.Height); p.Width = pArguments.ClientRectangle.Width; p.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; p.BorderStyle = BorderStyle.FixedSingle; p.Location = new Point(0, _currentY); _currentY += p.Height; name.Location = new Point(0, 0); p.Controls.Add(name); helpIcon.Left = name.Right; p.Controls.Add(helpIcon); ragSmiley.Left = p.Width - ragSmiley.Width; ragSmiley.Anchor = AnchorStyles.Right | AnchorStyles.Top; p.Controls.Add(ragSmiley); valueui.Left = helpIcon.Right; valueui.Width = p.Width - (helpIcon.Right + ragSmiley.Left); _maxValueUILeft = Math.Max(_maxValueUILeft, valueui.Left); p.Controls.Add(valueui); p.MinimumSize = new Size(ragSmiley.Right, p.Height); name.Height = p.Height; pArguments.Controls.Add(p); }
private IEnumerable <PreLoadDiscardedColumn> GetAllPreloadDiscardedColumnsInScope(ICatalogueRepository repository, IArgumentHost parent) { if (parent is ProcessTask || parent is LoadMetadata) { return(GetTableInfosInScope(repository, parent).SelectMany(t => t.PreLoadDiscardedColumns)); } return(repository.GetAllObjects <PreLoadDiscardedColumn>()); }
private IEnumerable <ColumnInfo> GetColumnInfosInScope(ICatalogueRepository repository, IArgumentHost parent) { if (parent is ProcessTask || parent is LoadMetadata) { return(GetTableInfosInScope(repository, parent).SelectMany(ti => ti.ColumnInfos)); } return(repository.GetAllObjects <ColumnInfo>()); }
private IEnumerable <TableInfo> GetTableInfosInScope(ICatalogueRepository repository, IArgumentHost parent) { if (parent is ProcessTask pt) { return(pt.GetTableInfos()); } if (parent is LoadMetadata lmd) { return(lmd.GetDistinctTableInfoList(true)); } return(repository.GetAllObjects <TableInfo>()); }