/// <summary> /// Reads an qualified object name from its defining element. Outputs an error if the name is missing. /// </summary> /// <param name="Element">Element to read the name for</param> /// <param name="QualifiedName">Output variable to receive the name of the object</param> /// <returns>True if the object had a valid name (assigned to the Name variable), false if the name was invalid or missing.</returns> bool TryReadQualifiedObjectName(ScriptElement Element, out string[] QualifiedName) { // Check the name attribute is present if (!Element.HasAttribute("Name")) { LogError(Element, "Missing 'Name' attribute"); QualifiedName = null; return(false); } // Get the value of it, strip any leading or trailing whitespace, and make sure it's not empty string[] Values = ReadAttribute(Element, "Name").Split('.'); foreach (string Value in Values) { if (!ValidateName(Element, Value)) { QualifiedName = null; return(false); } } // Return it QualifiedName = Values; return(true); }
/// <summary> /// Reads an attribute from the given XML element, expands any properties in it, and parses it as an enum of the given type. /// </summary> /// <typeparam name="T">The enum type to parse the attribute as</typeparam> /// <param name="Element">Element to read the attribute from</param> /// <param name="Name">Name of the attribute</param> /// <param name="DefaultValue">Default value for the enum, if the attribute is missing</param> /// <returns>The value of the attribute field</returns> T ReadEnumAttribute <T>(ScriptElement Element, string Name, T DefaultValue) where T : struct { T Result = DefaultValue; if (Element.HasAttribute(Name)) { string Value = ReadAttribute(Element, Name).Trim(); T EnumValue; if (Enum.TryParse(Value, true, out EnumValue)) { Result = EnumValue; } else { LogError(Element, "Invalid value '{0}' - expected {1}", Value, String.Join("/", Enum.GetNames(typeof(T)))); } } return(Result); }
/// <summary> /// Evaluates the (optional) conditional expression on a given XML element via the If="..." attribute, and returns true if the element is enabled. /// </summary> /// <param name="Element">The element to check</param> /// <returns>True if the element's condition evaluates to true (or doesn't have a conditional expression), false otherwise</returns> bool EvaluateCondition(ScriptElement Element) { // Check if the element has a conditional attribute const string AttributeName = "If"; if (!Element.HasAttribute(AttributeName)) { return(true); } // If it does, try to evaluate it. try { string Text = ExpandProperties(Element.GetAttribute("If")); return(Condition.Evaluate(Text)); } catch (ConditionException Ex) { LogError(Element, "Error in condition: {0}", Ex.Message); return(false); } }
/// <summary> /// Reads an attribute from the given XML element, expands any properties in it, and parses it as a boolean. /// </summary> /// <param name="Element">Element to read the attribute from</param> /// <param name="Name">Name of the attribute</param> /// <param name="DefaultValue">Default value if the attribute is missing</param> /// <returns>The value of the attribute field</returns> bool ReadBooleanAttribute(ScriptElement Element, string Name, bool bDefaultValue) { bool bResult = bDefaultValue; if (Element.HasAttribute(Name)) { string Value = ReadAttribute(Element, Name).Trim(); if (Value.Equals("true", StringComparison.InvariantCultureIgnoreCase)) { bResult = true; } else if (Value.Equals("false", StringComparison.InvariantCultureIgnoreCase)) { bResult = false; } else { LogError(Element, "Invalid boolean value '{0}' - expected 'true' or 'false'", Value); } } return(bResult); }
/// <summary> /// Reads an object name from its defining element. Outputs an error if the name is missing. /// </summary> /// <param name="Element">Element to read the name for</param> /// <param name="Name">Output variable to receive the name of the object</param> /// <returns>True if the object had a valid name (assigned to the Name variable), false if the name was invalid or missing.</returns> bool TryReadObjectName(ScriptElement Element, out string Name) { // Check the name attribute is present if (!Element.HasAttribute("Name")) { LogError(Element, "Missing 'Name' attribute"); Name = null; return(false); } // Get the value of it, strip any leading or trailing whitespace, and make sure it's not empty string Value = ReadAttribute(Element, "Name"); if (!ValidateName(Element, Value)) { Name = null; return(false); } // Return it Name = Value; return(true); }
/// <summary> /// Reads the definition for an email notifier /// </summary> /// <param name="Element">Xml element to read the definition from</param> void ReadNotifier(ScriptElement Element) { if (EvaluateCondition(Element)) { string[] TargetNames = ReadListAttribute(Element, "Targets"); string[] ExceptNames = ReadListAttribute(Element, "Except"); string[] IndividualNodeNames = ReadListAttribute(Element, "Nodes"); string[] TriggerNames = ReadListAttribute(Element, "Triggers"); string[] Users = ReadListAttribute(Element, "Users"); string[] Submitters = ReadListAttribute(Element, "Submitters"); bool? bWarnings = Element.HasAttribute("Warnings")? (bool?)ReadBooleanAttribute(Element, "Warnings", true) : null; // Find the list of targets which are included, and recurse through all their dependencies HashSet <Node> Nodes = new HashSet <Node>(); if (TargetNames != null) { HashSet <Node> TargetNodes = ResolveReferences(Element, TargetNames); foreach (Node Node in TargetNodes) { Nodes.Add(Node); Nodes.UnionWith(Node.InputDependencies); } } // Add all the individually referenced nodes if (IndividualNodeNames != null) { HashSet <Node> IndividualNodes = ResolveReferences(Element, IndividualNodeNames); Nodes.UnionWith(IndividualNodes); } // Exclude all the exceptions if (ExceptNames != null) { HashSet <Node> ExceptNodes = ResolveReferences(Element, ExceptNames); Nodes.ExceptWith(ExceptNodes); } // Update all the referenced nodes with the settings foreach (Node Node in Nodes) { if (Users != null) { Node.NotifyUsers.UnionWith(Users); } if (Submitters != null) { Node.NotifySubmitters.UnionWith(Submitters); } if (bWarnings.HasValue) { Node.bNotifyOnWarnings = bWarnings.Value; } } // Add the users to the list of triggers if (TriggerNames != null) { foreach (string TriggerName in TriggerNames) { ManualTrigger Trigger; if (Graph.NameToTrigger.TryGetValue(TriggerName, out Trigger)) { Trigger.NotifyUsers.UnionWith(Users); } else { LogError(Element, "Trigger '{0}' has not been defined", TriggerName); } } } } }
/// <summary> /// Reads a task definition from the given element, and add it to the given list /// </summary> /// <param name="Element">Xml element to read the definition from</param> /// <param name="Tasks">List of tasks to add to</param> void ReadTask(ScriptElement Element, List <CustomTask> Tasks) { if (EvaluateCondition(Element)) { // Get the reflection info for this element ScriptTask Task; if (!Schema.TryGetTask(Element.Name, out Task)) { LogError(Element, "Unknown task '{0}'", Element.Name); return; } // Check all the required parameters are present bool bHasRequiredAttributes = true; foreach (ScriptTaskParameter Parameter in Task.NameToParameter.Values) { if (!Parameter.bOptional && !Element.HasAttribute(Parameter.Name)) { LogError(Element, "Missing required attribute - {0}", Parameter.Name); bHasRequiredAttributes = false; } } // Read all the attributes into a parameters object for this task object ParametersObject = Activator.CreateInstance(Task.ParametersClass); foreach (XmlAttribute Attribute in Element.Attributes) { if (String.Compare(Attribute.Name, "If", StringComparison.InvariantCultureIgnoreCase) != 0) { // Get the field that this attribute should be written to in the parameters object ScriptTaskParameter Parameter; if (!Task.NameToParameter.TryGetValue(Attribute.Name, out Parameter)) { LogError(Element, "Unknown attribute '{0}'", Attribute.Name); continue; } // Expand variables in the value string ExpandedValue = ExpandProperties(Attribute.Value); // Parse it and assign it to the parameters object object Value; if (Parameter.FieldInfo.FieldType.IsEnum) { Value = Enum.Parse(Parameter.FieldInfo.FieldType, ExpandedValue); } else if (Parameter.FieldInfo.FieldType == typeof(Boolean)) { Value = Condition.Evaluate(ExpandedValue); } else { Value = Convert.ChangeType(ExpandedValue, Parameter.FieldInfo.FieldType); } Parameter.FieldInfo.SetValue(ParametersObject, Value); } } // Construct the task if (bHasRequiredAttributes) { Tasks.Add((CustomTask)Activator.CreateInstance(Task.TaskClass, ParametersObject)); } } }