// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Schema; using EpicGames.BuildGraph; using EpicGames.Core; #nullable enable namespace AutomationTool { /// /// Specifies validation that should be performed on a task parameter. /// public enum TaskParameterValidationType { /// /// Allow any valid values for the field type. /// Default, /// /// A list of tag names separated by semicolons /// TagList, /// /// A file specification, which may contain tags and wildcards. /// FileSpec, } /// /// Information about a parameter to a task /// [DebuggerDisplay("{Name}")] public class BgScriptTaskParameter { /// /// Name of this parameter /// public string Name { get; } /// /// The type for values assigned to this field /// public Type ValueType { get; } /// /// The ICollection interface for this type /// public Type? CollectionType { get; } /// /// Validation type for this field /// public TaskParameterValidationType ValidationType { get; } /// /// Whether this parameter is optional /// public bool Optional { get; } /// /// Constructor /// public BgScriptTaskParameter(string name, Type valueType, TaskParameterValidationType validationType, bool optional) { Name = name; ValueType = valueType; ValidationType = validationType; Optional = optional; if (ValueType.IsGenericType && ValueType.GetGenericTypeDefinition() == typeof(Nullable<>)) { ValueType = ValueType.GetGenericArguments()[0]; Optional = true; } if (ValueType.IsClass) { foreach (Type interfaceType in ValueType.GetInterfaces()) { if (interfaceType.IsGenericType) { Type genericInterfaceType = interfaceType.GetGenericTypeDefinition(); if (genericInterfaceType == typeof(ICollection<>)) { CollectionType = interfaceType; ValueType = interfaceType.GetGenericArguments()[0]; } } } } } } /// /// Helper class to serialize a task from an xml element /// [DebuggerDisplay("{Name}")] public class BgScriptTask { /// /// Name of this task /// public string Name { get; } /// /// Parameters for this task /// public List Parameters { get; } /// /// Constructor /// /// Name of the task /// Parameters for the task public BgScriptTask(string name, List parameters) { Name = name; Parameters = new List(parameters); } } #pragma warning disable CS1591 /// /// Enumeration of standard types used in the schema. Avoids hard-coding names. /// public enum ScriptSchemaStandardType { Graph, Agent, AgentBody, Node, NodeBody, Aggregate, Artifact, Report, Badge, Label, Notify, Include, Option, EnvVar, Property, Regex, StringOp, Macro, MacroBody, Extend, Expand, Annotate, Trace, Warning, Error, Name, NameList, Tag, TagList, NameOrTag, NameOrTagList, QualifiedName, BalancedString, Boolean, Integer, LabelChange } #pragma warning restore CS1591 /// /// Schema for build graph definitions. Stores information about the supported tasks, and allows validating an XML document. /// public class BgScriptSchema { /// /// Name of the root element /// public const string RootElementName = "BuildGraph"; /// /// Namespace for the schema /// public const string NamespaceUri = "http://www.epicgames.com/BuildGraph"; /// /// Qualified name for the string type /// static readonly XmlQualifiedName s_stringTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema"); /// /// The inner xml schema /// public XmlSchema CompiledSchema { get; } /// /// Characters which are not permitted in names. /// public const string IllegalNameCharacters = "^<>:\"/\\|?*"; /// /// Pattern which matches any name; alphanumeric characters, with single embedded spaces. /// const string NamePattern = "[^ " + IllegalNameCharacters + "]+( [^ " + IllegalNameCharacters + "]+)*"; /// /// Pattern which matches a list of names, separated by semicolons. /// const string NameListPattern = NamePattern + "(;" + NamePattern + ")*"; /// /// Pattern which matches any tag name; a name with a leading '#' character /// const string TagPattern = "#" + NamePattern; /// /// Pattern which matches a list of tag names, separated by semicolons; /// const string TagListPattern = TagPattern + "(;" + TagPattern + ")*"; /// /// Pattern which matches any name or tag name; a name with a leading '#' character /// const string NameOrTagPattern = "#?" + NamePattern; /// /// Pattern which matches a list of names or tag names, separated by semicolons; /// const string NameOrTagListPattern = NameOrTagPattern + "(;" + NameOrTagPattern + ")*"; /// /// Pattern which matches a qualified name. /// const string QualifiedNamePattern = NamePattern + "(\\." + NamePattern + ")*"; /// /// Pattern which matches a property name /// const string PropertyPattern = "\\$\\(" + NamePattern + "\\)"; /// /// Pattern which matches balanced parentheses in a string /// const string StringWithPropertiesPattern = "[^\\$]*" + "(" + "(" + PropertyPattern + "|" + "\\$[^\\(]" + ")" + "[^\\$]*" + ")+" + "\\$?"; /// /// Pattern which matches balanced parentheses in a string /// const string BalancedStringPattern = "[^\\$]*" + "(" + "(" + PropertyPattern + "|" + "\\$[^\\(]" + ")" + "[^\\$]*" + ")*" + "\\$?"; private BgScriptSchema(XmlSchema schema) { CompiledSchema = schema; } /// /// Constructor /// /// Set of known tasks /// Mapping of task name to information about how to construct it public BgScriptSchema(IEnumerable tasks, List<(Type, ScriptSchemaStandardType)> primitiveTypes) { // Create a lookup from standard types to their qualified names Dictionary typeToSchemaTypeName = new Dictionary(); typeToSchemaTypeName.Add(typeof(string), GetQualifiedTypeName(ScriptSchemaStandardType.BalancedString)); typeToSchemaTypeName.Add(typeof(bool), GetQualifiedTypeName(ScriptSchemaStandardType.Boolean)); typeToSchemaTypeName.Add(typeof(int), GetQualifiedTypeName(ScriptSchemaStandardType.Integer)); foreach ((Type type, ScriptSchemaStandardType schemaType) in primitiveTypes) { typeToSchemaTypeName.Add(type, GetQualifiedTypeName(schemaType)); } // Create all the custom user types, and add them to the qualified name lookup List userTypes = new List(); foreach (Type type in tasks.SelectMany(x => x.Parameters).Select(x => x.ValueType)) { if (!typeToSchemaTypeName.ContainsKey(type)) { if (type.IsClass && type.GetInterfaces().Any(x => x.GetGenericTypeDefinition() == typeof(ICollection<>))) { typeToSchemaTypeName.Add(type, GetQualifiedTypeName(ScriptSchemaStandardType.BalancedString)); } else { string name = type.Name + "UserType"; XmlSchemaType schemaType = CreateUserType(name, type); userTypes.Add(schemaType); typeToSchemaTypeName.Add(type, new XmlQualifiedName(name, NamespaceUri)); } } } // Create all the task types Dictionary taskNameToType = new Dictionary(); foreach (BgScriptTask task in tasks) { XmlSchemaComplexType taskType = new XmlSchemaComplexType(); taskType.Name = task.Name + "TaskType"; foreach (BgScriptTaskParameter parameter in task.Parameters) { XmlQualifiedName? schemaTypeName = GetQualifiedTypeName(parameter.ValidationType); if (schemaTypeName == null) { schemaTypeName = typeToSchemaTypeName[parameter.ValueType]; } taskType.Attributes.Add(CreateSchemaAttribute(parameter.Name, schemaTypeName, parameter.Optional ? XmlSchemaUse.Optional : XmlSchemaUse.Required)); } taskType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); taskNameToType.Add(task.Name, taskType); } // Create the schema object XmlSchema newSchema = new XmlSchema(); newSchema.TargetNamespace = NamespaceUri; newSchema.ElementFormDefault = XmlSchemaForm.Qualified; newSchema.Items.Add(CreateSchemaElement(RootElementName, ScriptSchemaStandardType.Graph)); newSchema.Items.Add(CreateGraphType()); newSchema.Items.Add(CreateAgentType()); newSchema.Items.Add(CreateAgentBodyType()); newSchema.Items.Add(CreateNodeType()); newSchema.Items.Add(CreateNodeBodyType(taskNameToType)); newSchema.Items.Add(CreateAggregateType()); newSchema.Items.Add(CreateArtifactType()); newSchema.Items.Add(CreateReportType()); newSchema.Items.Add(CreateBadgeType()); newSchema.Items.Add(CreateLabelType()); newSchema.Items.Add(CreateEnumType(GetTypeName(ScriptSchemaStandardType.LabelChange), typeof(BgLabelChange))); newSchema.Items.Add(CreateNotifyType()); newSchema.Items.Add(CreateIncludeType()); newSchema.Items.Add(CreateOptionType()); newSchema.Items.Add(CreateEnvVarType()); newSchema.Items.Add(CreatePropertyType()); newSchema.Items.Add(CreateRegexType()); newSchema.Items.Add(CreateStringOpType()); newSchema.Items.Add(CreateMacroType()); newSchema.Items.Add(CreateMacroBodyType(taskNameToType)); newSchema.Items.Add(CreateExtendType()); newSchema.Items.Add(CreateExpandType()); newSchema.Items.Add(CreateAnnotateType()); newSchema.Items.Add(CreateDiagnosticType(ScriptSchemaStandardType.Trace)); newSchema.Items.Add(CreateDiagnosticType(ScriptSchemaStandardType.Warning)); newSchema.Items.Add(CreateDiagnosticType(ScriptSchemaStandardType.Error)); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.Name), "(" + NamePattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.NameList), "(" + NameListPattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.Tag), "(" + TagPattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.TagList), "(" + TagListPattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.NameOrTag), "(" + NameOrTagPattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.NameOrTagList), "(" + NameOrTagListPattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.QualifiedName), "(" + QualifiedNamePattern + "|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.BalancedString), BalancedStringPattern)); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.Boolean), "(true|True|false|False|" + StringWithPropertiesPattern + ")")); newSchema.Items.Add(CreateSimpleTypeFromRegex(GetTypeName(ScriptSchemaStandardType.Integer), "(" + "(-?[1-9][0-9]*|0)" + "|" + StringWithPropertiesPattern + ")")); foreach (XmlSchemaComplexType type in taskNameToType.Values) { newSchema.Items.Add(type); } foreach (XmlSchemaSimpleType type in userTypes) { newSchema.Items.Add(type); } // Now that we've finished, compile it and store it to the class XmlSchemaSet newSchemaSet = new XmlSchemaSet(); newSchemaSet.Add(newSchema); newSchemaSet.Compile(); XmlSchema? schema = null; foreach (XmlSchema? newCompiledSchema in newSchemaSet.Schemas()) { schema = newCompiledSchema!; } CompiledSchema = schema!; } /// /// Export the schema to a file /// /// public void Export(FileReference file) { DirectoryReference.CreateDirectory(file.Directory); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = " "; settings.NewLineChars = "\n"; DirectoryReference.CreateDirectory(file.Directory); using (XmlWriter writer = XmlWriter.Create(file.FullName, settings)) { CompiledSchema.Write(writer); } } /// /// Imports a schema from a file /// /// The XML file to import /// A deserialized from the XML file, or null if file doesn't exist public static BgScriptSchema? Import(FileReference file) { if (!FileReference.Exists(file)) { return null; } using (XmlReader schemaFile = XmlReader.Create(file.FullName)) { BgScriptSchema importedSchema = new BgScriptSchema(XmlSchema.Read(schemaFile, ValidationCallback)!); return importedSchema; } } static void ValidationCallback(object? sender, ValidationEventArgs eventArgs) { if (eventArgs.Severity == XmlSeverityType.Warning) { Log.WriteLine(LogEventType.Warning, "WARNING: {0}", eventArgs.Message); } else if (eventArgs.Severity == XmlSeverityType.Error) { Log.WriteLine(LogEventType.Error, "ERROR: {0}", eventArgs.Message); } } /// /// Gets the bare name for the given script type /// /// Script type to find the name of /// Name of the schema type that matches the given script type static string GetTypeName(ScriptSchemaStandardType type) { return type.ToString() + "Type"; } /// /// Gets the qualified name for the given script type /// /// Script type to find the qualified name for /// Qualified name of the schema type that matches the given script type static XmlQualifiedName GetQualifiedTypeName(ScriptSchemaStandardType type) { return new XmlQualifiedName(GetTypeName(type), NamespaceUri); } /// /// Gets the qualified name of the schema type for the given type of validation /// /// Qualified name for the corresponding schema type static XmlQualifiedName? GetQualifiedTypeName(TaskParameterValidationType type) { switch (type) { case TaskParameterValidationType.TagList: return GetQualifiedTypeName(ScriptSchemaStandardType.TagList); } return null; } /// /// Creates the schema type representing the graph type /// /// Type definition for a graph static XmlSchemaType CreateGraphType() { XmlSchemaChoice graphChoice = new XmlSchemaChoice(); graphChoice.MinOccurs = 0; graphChoice.MaxOccursString = "unbounded"; graphChoice.Items.Add(CreateSchemaElement("Include", ScriptSchemaStandardType.Include)); graphChoice.Items.Add(CreateSchemaElement("Option", ScriptSchemaStandardType.Option)); graphChoice.Items.Add(CreateSchemaElement("EnvVar", ScriptSchemaStandardType.EnvVar)); graphChoice.Items.Add(CreateSchemaElement("Property", ScriptSchemaStandardType.Property)); graphChoice.Items.Add(CreateSchemaElement("Regex", ScriptSchemaStandardType.Regex)); graphChoice.Items.Add(CreateSchemaElement("StringOp", ScriptSchemaStandardType.StringOp)); graphChoice.Items.Add(CreateSchemaElement("Macro", ScriptSchemaStandardType.Macro)); graphChoice.Items.Add(CreateSchemaElement("Extend", ScriptSchemaStandardType.Extend)); graphChoice.Items.Add(CreateSchemaElement("Agent", ScriptSchemaStandardType.Agent)); graphChoice.Items.Add(CreateSchemaElement("Aggregate", ScriptSchemaStandardType.Aggregate)); graphChoice.Items.Add(CreateSchemaElement("Artifact", ScriptSchemaStandardType.Artifact)); graphChoice.Items.Add(CreateSchemaElement("Report", ScriptSchemaStandardType.Report)); graphChoice.Items.Add(CreateSchemaElement("Badge", ScriptSchemaStandardType.Badge)); graphChoice.Items.Add(CreateSchemaElement("Label", ScriptSchemaStandardType.Label)); graphChoice.Items.Add(CreateSchemaElement("Notify", ScriptSchemaStandardType.Notify)); graphChoice.Items.Add(CreateSchemaElement("Annotate", ScriptSchemaStandardType.Annotate)); graphChoice.Items.Add(CreateSchemaElement("Trace", ScriptSchemaStandardType.Trace)); graphChoice.Items.Add(CreateSchemaElement("Warning", ScriptSchemaStandardType.Warning)); graphChoice.Items.Add(CreateSchemaElement("Error", ScriptSchemaStandardType.Error)); graphChoice.Items.Add(CreateSchemaElement("Expand", ScriptSchemaStandardType.Expand)); graphChoice.Items.Add(CreateDoElement(ScriptSchemaStandardType.Graph)); graphChoice.Items.Add(CreateSwitchElement(ScriptSchemaStandardType.Graph)); graphChoice.Items.Add(CreateForEachElement(ScriptSchemaStandardType.Graph)); XmlSchemaComplexType graphType = new XmlSchemaComplexType(); graphType.Name = GetTypeName(ScriptSchemaStandardType.Graph); graphType.Particle = graphChoice; return graphType; } /// /// Creates the schema type representing the agent type /// /// Type definition for an agent static XmlSchemaType CreateAgentType() { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(ScriptSchemaStandardType.AgentBody); extension.Attributes.Add(CreateSchemaAttribute("Name", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Type", ScriptSchemaStandardType.NameList, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType complexType = new XmlSchemaComplexType(); complexType.Name = GetTypeName(ScriptSchemaStandardType.Agent); complexType.ContentModel = contentModel; return complexType; } /// /// Creates the schema type representing the contents of agent type /// /// Type definition for an agent static XmlSchemaType CreateAgentBodyType() { XmlSchemaChoice agentChoice = new XmlSchemaChoice(); agentChoice.MinOccurs = 0; agentChoice.MaxOccursString = "unbounded"; agentChoice.Items.Add(CreateSchemaElement("Property", ScriptSchemaStandardType.Property)); agentChoice.Items.Add(CreateSchemaElement("Regex", ScriptSchemaStandardType.Regex)); agentChoice.Items.Add(CreateSchemaElement("StringOp", ScriptSchemaStandardType.StringOp)); agentChoice.Items.Add(CreateSchemaElement("EnvVar", ScriptSchemaStandardType.EnvVar)); agentChoice.Items.Add(CreateSchemaElement("Node", ScriptSchemaStandardType.Node)); agentChoice.Items.Add(CreateSchemaElement("Trace", ScriptSchemaStandardType.Trace)); agentChoice.Items.Add(CreateSchemaElement("Label", ScriptSchemaStandardType.Label)); agentChoice.Items.Add(CreateSchemaElement("Annotate", ScriptSchemaStandardType.Annotate)); agentChoice.Items.Add(CreateSchemaElement("Artifact", ScriptSchemaStandardType.Artifact)); agentChoice.Items.Add(CreateSchemaElement("Warning", ScriptSchemaStandardType.Warning)); agentChoice.Items.Add(CreateSchemaElement("Error", ScriptSchemaStandardType.Error)); agentChoice.Items.Add(CreateSchemaElement("Expand", ScriptSchemaStandardType.Expand)); agentChoice.Items.Add(CreateDoElement(ScriptSchemaStandardType.AgentBody)); agentChoice.Items.Add(CreateSwitchElement(ScriptSchemaStandardType.AgentBody)); agentChoice.Items.Add(CreateForEachElement(ScriptSchemaStandardType.AgentBody)); XmlSchemaComplexType agentType = new XmlSchemaComplexType(); agentType.Name = GetTypeName(ScriptSchemaStandardType.AgentBody); agentType.Particle = agentChoice; return agentType; } /// /// Creates the schema type representing the node type /// /// Type definition for a node static XmlSchemaType CreateNodeType() { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(ScriptSchemaStandardType.NodeBody); extension.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Requires", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("Produces", ScriptSchemaStandardType.TagList, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("After", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("Token", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("RunEarly", ScriptSchemaStandardType.Boolean, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("NotifyOnWarnings", ScriptSchemaStandardType.Boolean, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("Annotations", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("IgnoreModified", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType complexType = new XmlSchemaComplexType(); complexType.Name = GetTypeName(ScriptSchemaStandardType.Node); complexType.ContentModel = contentModel; return complexType; } /// /// Creates the schema type representing the body of the node type /// /// Type definition for a node static XmlSchemaType CreateNodeBodyType(Dictionary taskNameToType) { XmlSchemaChoice nodeChoice = new XmlSchemaChoice(); nodeChoice.MinOccurs = 0; nodeChoice.MaxOccursString = "unbounded"; nodeChoice.Items.Add(CreateSchemaElement("Property", ScriptSchemaStandardType.Property)); nodeChoice.Items.Add(CreateSchemaElement("Regex", ScriptSchemaStandardType.Regex)); nodeChoice.Items.Add(CreateSchemaElement("StringOp", ScriptSchemaStandardType.StringOp)); nodeChoice.Items.Add(CreateSchemaElement("EnvVar", ScriptSchemaStandardType.EnvVar)); nodeChoice.Items.Add(CreateSchemaElement("Trace", ScriptSchemaStandardType.Trace)); nodeChoice.Items.Add(CreateSchemaElement("Warning", ScriptSchemaStandardType.Warning)); nodeChoice.Items.Add(CreateSchemaElement("Error", ScriptSchemaStandardType.Error)); nodeChoice.Items.Add(CreateSchemaElement("Expand", ScriptSchemaStandardType.Expand)); nodeChoice.Items.Add(CreateDoElement(ScriptSchemaStandardType.NodeBody)); nodeChoice.Items.Add(CreateSwitchElement(ScriptSchemaStandardType.NodeBody)); nodeChoice.Items.Add(CreateForEachElement(ScriptSchemaStandardType.NodeBody)); if (taskNameToType == null) { nodeChoice.Items.Add(new XmlSchemaAny()); } else { foreach (KeyValuePair pair in taskNameToType.OrderBy(x => x.Key)) { nodeChoice.Items.Add(CreateSchemaElement(pair.Key, new XmlQualifiedName(pair.Value.Name, NamespaceUri))); } } XmlSchemaComplexType nodeType = new XmlSchemaComplexType(); nodeType.Name = GetTypeName(ScriptSchemaStandardType.NodeBody); nodeType.Particle = nodeChoice; return nodeType; } /// /// Creates the schema type representing the aggregate type /// /// Type definition for an aggregate static XmlSchemaType CreateAggregateType() { XmlSchemaComplexType aggregateType = new XmlSchemaComplexType(); aggregateType.Name = GetTypeName(ScriptSchemaStandardType.Aggregate); aggregateType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); aggregateType.Attributes.Add(CreateSchemaAttribute("Label", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Requires", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Required)); aggregateType.Attributes.Add(CreateSchemaAttribute("Include", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Exclude", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return aggregateType; } /// /// Creates the schema type representing the artifact type /// /// Type definition for an artifact static XmlSchemaType CreateArtifactType() { XmlSchemaComplexType artifactType = new XmlSchemaComplexType(); artifactType.Name = GetTypeName(ScriptSchemaStandardType.Artifact); artifactType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); artifactType.Attributes.Add(CreateSchemaAttribute("Type", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); artifactType.Attributes.Add(CreateSchemaAttribute("Description", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); artifactType.Attributes.Add(CreateSchemaAttribute("BasePath", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); artifactType.Attributes.Add(CreateSchemaAttribute("Tag", ScriptSchemaStandardType.Tag, XmlSchemaUse.Optional)); artifactType.Attributes.Add(CreateSchemaAttribute("Keys", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); artifactType.Attributes.Add(CreateSchemaAttribute("Metadata", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); artifactType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return artifactType; } /// /// Creates the schema type representing the report type /// /// Type definition for a report static XmlSchemaType CreateReportType() { XmlSchemaComplexType reportType = new XmlSchemaComplexType(); reportType.Name = GetTypeName(ScriptSchemaStandardType.Report); reportType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); reportType.Attributes.Add(CreateSchemaAttribute("Requires", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Required)); reportType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return reportType; } /// /// Creates the schema type representing the badge type /// /// Type definition for a badge static XmlSchemaType CreateBadgeType() { XmlSchemaComplexType badgeType = new XmlSchemaComplexType(); badgeType.Name = GetTypeName(ScriptSchemaStandardType.Badge); badgeType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); badgeType.Attributes.Add(CreateSchemaAttribute("Requires", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); badgeType.Attributes.Add(CreateSchemaAttribute("Targets", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); badgeType.Attributes.Add(CreateSchemaAttribute("Project", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); badgeType.Attributes.Add(CreateSchemaAttribute("Change", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); badgeType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return badgeType; } /// /// Creates the schema type representing the label type /// /// Type definition for a label static XmlSchemaType CreateLabelType() { XmlSchemaComplexType labelType = new XmlSchemaComplexType(); labelType.Name = GetTypeName(ScriptSchemaStandardType.Label); labelType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("Category", ScriptSchemaStandardType.Name, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("UgsBadge", ScriptSchemaStandardType.Name, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("UgsProject", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("Change", ScriptSchemaStandardType.LabelChange, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("Requires", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Required)); labelType.Attributes.Add(CreateSchemaAttribute("Include", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("Exclude", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); labelType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return labelType; } /// /// Creates the schema type representing a notifier /// /// Type definition for a notifier static XmlSchemaType CreateNotifyType() { XmlSchemaComplexType aggregateType = new XmlSchemaComplexType(); aggregateType.Name = GetTypeName(ScriptSchemaStandardType.Notify); aggregateType.Attributes.Add(CreateSchemaAttribute("Targets", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Except", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Nodes", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Reports", ScriptSchemaStandardType.NameList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Users", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Submitters", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Warnings", ScriptSchemaStandardType.Boolean, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Absolute", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return aggregateType; } /// /// Creates the schema type representing an annotation /// /// Type definition for a notifier static XmlSchemaType CreateAnnotateType() { XmlSchemaComplexType aggregateType = new XmlSchemaComplexType(); aggregateType.Name = GetTypeName(ScriptSchemaStandardType.Annotate); aggregateType.Attributes.Add(CreateSchemaAttribute("Targets", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Except", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Nodes", ScriptSchemaStandardType.NameOrTagList, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("Values", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); aggregateType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return aggregateType; } /// /// Creates the schema type representing an include type /// /// Type definition for an include directive static XmlSchemaType CreateIncludeType() { XmlSchemaComplexType propertyType = new XmlSchemaComplexType(); propertyType.Name = GetTypeName(ScriptSchemaStandardType.Include); propertyType.Attributes.Add(CreateSchemaAttribute("Script", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); propertyType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); propertyType.Attributes.Add(CreateSchemaAttribute("IgnoreDuplicateIncludes", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return propertyType; } /// /// Creates the schema type representing a parameter type /// /// Type definition for a parameter static XmlSchemaType CreateOptionType() { XmlSchemaComplexType optionType = new XmlSchemaComplexType(); optionType.Name = GetTypeName(ScriptSchemaStandardType.Option); optionType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); optionType.Attributes.Add(CreateSchemaAttribute("Restrict", s_stringTypeName, XmlSchemaUse.Optional)); optionType.Attributes.Add(CreateSchemaAttribute("DefaultValue", s_stringTypeName, XmlSchemaUse.Required)); optionType.Attributes.Add(CreateSchemaAttribute("Description", s_stringTypeName, XmlSchemaUse.Required)); optionType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return optionType; } /// /// Creates the schema type representing a environment variable type /// /// Type definition for an environment variable property static XmlSchemaType CreateEnvVarType() { XmlSchemaComplexType envVarType = new XmlSchemaComplexType(); envVarType.Name = GetTypeName(ScriptSchemaStandardType.EnvVar); envVarType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); envVarType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return envVarType; } /// /// Creates the schema type representing a property type /// /// Type definition for a property static XmlSchemaType CreatePropertyType() { XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension(); extension.BaseTypeName = s_stringTypeName; extension.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Value", s_stringTypeName, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("Separator", s_stringTypeName, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("Multiline", s_stringTypeName, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("CreateInParentScope", ScriptSchemaStandardType.Boolean, XmlSchemaUse.Optional)); XmlSchemaSimpleContent contentModel = new XmlSchemaSimpleContent(); contentModel.Content = extension; XmlSchemaComplexType propertyType = new XmlSchemaComplexType(); propertyType.Name = GetTypeName(ScriptSchemaStandardType.Property); propertyType.ContentModel = contentModel; return propertyType; } /// /// Creates the schema type representing a regex type /// /// Type definition for a regex static XmlSchemaType CreateRegexType() { XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension(); extension.BaseTypeName = s_stringTypeName; extension.Attributes.Add(CreateSchemaAttribute("Input", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Pattern", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Capture", ScriptSchemaStandardType.NameList, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Optional", ScriptSchemaStandardType.Boolean, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaSimpleContent contentModel = new XmlSchemaSimpleContent(); contentModel.Content = extension; XmlSchemaComplexType regexType = new XmlSchemaComplexType(); regexType.Name = GetTypeName(ScriptSchemaStandardType.Regex); regexType.ContentModel = contentModel; return regexType; } /// /// Creates the schema type representing a stringop type /// /// Type definition for a stringop element static XmlSchemaType CreateStringOpType() { XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension(); extension.BaseTypeName = s_stringTypeName; extension.Attributes.Add(CreateSchemaAttribute("Input", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Output", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Method", s_stringTypeName, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Arguments", s_stringTypeName, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaSimpleContent contentModel = new XmlSchemaSimpleContent(); contentModel.Content = extension; XmlSchemaComplexType stringOpType = new XmlSchemaComplexType(); stringOpType.Name = GetTypeName(ScriptSchemaStandardType.StringOp); stringOpType.ContentModel = contentModel; return stringOpType; } /// /// Creates the schema type representing the macro type /// /// Type definition for a node static XmlSchemaType CreateMacroType() { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(ScriptSchemaStandardType.MacroBody); extension.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Arguments", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("OptionalArguments", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType complexType = new XmlSchemaComplexType(); complexType.Name = GetTypeName(ScriptSchemaStandardType.Macro); complexType.ContentModel = contentModel; return complexType; } /// /// Creates the schema type representing the macro type /// /// Type definition for a node static XmlSchemaType CreateMacroBodyType(Dictionary taskNameToType) { XmlSchemaChoice macroChoice = new XmlSchemaChoice(); macroChoice.MinOccurs = 0; macroChoice.MaxOccursString = "unbounded"; // Graph scope macroChoice.Items.Add(CreateSchemaElement("Include", ScriptSchemaStandardType.Include)); macroChoice.Items.Add(CreateSchemaElement("Option", ScriptSchemaStandardType.Option)); macroChoice.Items.Add(CreateSchemaElement("EnvVar", ScriptSchemaStandardType.EnvVar)); macroChoice.Items.Add(CreateSchemaElement("Property", ScriptSchemaStandardType.Property)); macroChoice.Items.Add(CreateSchemaElement("Regex", ScriptSchemaStandardType.Regex)); macroChoice.Items.Add(CreateSchemaElement("StringOp", ScriptSchemaStandardType.StringOp)); macroChoice.Items.Add(CreateSchemaElement("Macro", ScriptSchemaStandardType.Macro)); macroChoice.Items.Add(CreateSchemaElement("Agent", ScriptSchemaStandardType.Agent)); macroChoice.Items.Add(CreateSchemaElement("Aggregate", ScriptSchemaStandardType.Aggregate)); macroChoice.Items.Add(CreateSchemaElement("Artifact", ScriptSchemaStandardType.Artifact)); macroChoice.Items.Add(CreateSchemaElement("Report", ScriptSchemaStandardType.Report)); macroChoice.Items.Add(CreateSchemaElement("Badge", ScriptSchemaStandardType.Badge)); macroChoice.Items.Add(CreateSchemaElement("Notify", ScriptSchemaStandardType.Notify)); macroChoice.Items.Add(CreateSchemaElement("Trace", ScriptSchemaStandardType.Trace)); macroChoice.Items.Add(CreateSchemaElement("Warning", ScriptSchemaStandardType.Warning)); macroChoice.Items.Add(CreateSchemaElement("Error", ScriptSchemaStandardType.Error)); macroChoice.Items.Add(CreateSchemaElement("Expand", ScriptSchemaStandardType.Expand)); macroChoice.Items.Add(CreateSchemaElement("Label", ScriptSchemaStandardType.Label)); // Agent scope macroChoice.Items.Add(CreateSchemaElement("Node", ScriptSchemaStandardType.Node)); // Node scope macroChoice.Items.Add(CreateDoElement(ScriptSchemaStandardType.NodeBody)); macroChoice.Items.Add(CreateSwitchElement(ScriptSchemaStandardType.NodeBody)); macroChoice.Items.Add(CreateForEachElement(ScriptSchemaStandardType.NodeBody)); foreach (KeyValuePair pair in taskNameToType.OrderBy(x => x.Key)) { macroChoice.Items.Add(CreateSchemaElement(pair.Key, new XmlQualifiedName(pair.Value.Name, NamespaceUri))); } XmlSchemaComplexType nodeType = new XmlSchemaComplexType(); nodeType.Name = GetTypeName(ScriptSchemaStandardType.MacroBody); nodeType.Particle = macroChoice; return nodeType; } /// /// Creates the schema type representing the macro type /// /// Type definition for a node static XmlSchemaType CreateExtendType() { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(ScriptSchemaStandardType.MacroBody); extension.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.Name, XmlSchemaUse.Required)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType complexType = new XmlSchemaComplexType(); complexType.Name = GetTypeName(ScriptSchemaStandardType.Extend); complexType.ContentModel = contentModel; return complexType; } /// /// Creates the schema type representing a macro expansion /// /// Type definition for expanding a macro static XmlSchemaType CreateExpandType() { XmlSchemaAnyAttribute anyAttribute = new XmlSchemaAnyAttribute(); anyAttribute.ProcessContents = XmlSchemaContentProcessing.Skip; XmlSchemaComplexType propertyType = new XmlSchemaComplexType(); propertyType.Name = GetTypeName(ScriptSchemaStandardType.Expand); propertyType.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); propertyType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); propertyType.AnyAttribute = anyAttribute; return propertyType; } /// /// Creates the schema type representing a warning or error type /// /// Type definition for a warning static XmlSchemaType CreateDiagnosticType(ScriptSchemaStandardType standardType) { XmlSchemaComplexType propertyType = new XmlSchemaComplexType(); propertyType.Name = GetTypeName(standardType); propertyType.Attributes.Add(CreateSchemaAttribute("Message", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); propertyType.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); return propertyType; } /// /// Creates an element representing a conditional "Do" block, which recursively contains another type /// /// The base type for the do block to contain /// New schema element for the block static XmlSchemaElement CreateDoElement(ScriptSchemaStandardType innerType) { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(innerType); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType schemaType = new XmlSchemaComplexType(); schemaType.ContentModel = contentModel; XmlSchemaElement element = new XmlSchemaElement(); element.Name = "Do"; element.SchemaType = schemaType; return element; } /// /// Creates an element representing a conditional "Switch" block, which recursively contains another type /// /// The base type for the do block to contain /// New schema element for the block static XmlSchemaElement CreateSwitchElement(ScriptSchemaStandardType innerType) { // Create the "Option" element XmlSchemaComplexContentExtension caseExtension = new XmlSchemaComplexContentExtension(); caseExtension.BaseTypeName = GetQualifiedTypeName(innerType); caseExtension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); XmlSchemaComplexContent caseContentModel = new XmlSchemaComplexContent(); caseContentModel.Content = caseExtension; XmlSchemaComplexType caseSchemaType = new XmlSchemaComplexType(); caseSchemaType.ContentModel = caseContentModel; XmlSchemaElement caseElement = new XmlSchemaElement(); caseElement.Name = "Case"; caseElement.SchemaType = caseSchemaType; caseElement.MinOccurs = 0; caseElement.MaxOccursString = "unbounded"; // Create the "Otherwise" element XmlSchemaElement otherwiseElement = new XmlSchemaElement(); otherwiseElement.Name = "Default"; otherwiseElement.SchemaTypeName = GetQualifiedTypeName(innerType); otherwiseElement.MinOccurs = 0; otherwiseElement.MaxOccurs = 1; // Create the "Switch" element XmlSchemaSequence switchSequence = new XmlSchemaSequence(); switchSequence.Items.Add(caseElement); switchSequence.Items.Add(otherwiseElement); XmlSchemaComplexType switchSchemaType = new XmlSchemaComplexType(); switchSchemaType.Particle = switchSequence; XmlSchemaElement switchElement = new XmlSchemaElement(); switchElement.Name = "Switch"; switchElement.SchemaType = switchSchemaType; return switchElement; } /// /// Creates an element representing a conditional "ForEach" block, which recursively contains another type /// /// The base type for the foreach block to contain /// New schema element for the block static XmlSchemaElement CreateForEachElement(ScriptSchemaStandardType innerType) { XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension(); extension.BaseTypeName = GetQualifiedTypeName(innerType); extension.Attributes.Add(CreateSchemaAttribute("Name", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Values", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Required)); extension.Attributes.Add(CreateSchemaAttribute("Separator", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); extension.Attributes.Add(CreateSchemaAttribute("If", ScriptSchemaStandardType.BalancedString, XmlSchemaUse.Optional)); XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent(); contentModel.Content = extension; XmlSchemaComplexType schemaType = new XmlSchemaComplexType(); schemaType.ContentModel = contentModel; XmlSchemaElement element = new XmlSchemaElement(); element.Name = "ForEach"; element.SchemaType = schemaType; return element; } /// /// Constructs an XmlSchemaElement and initializes it with the given parameters /// /// Element name /// Type enumeration for the attribute /// A new XmlSchemaElement object static XmlSchemaElement CreateSchemaElement(string name, ScriptSchemaStandardType schemaType) { return CreateSchemaElement(name, GetQualifiedTypeName(schemaType)); } /// /// Constructs an XmlSchemaElement and initializes it with the given parameters /// /// Element name /// Qualified name of the type for this element /// A new XmlSchemaElement object static XmlSchemaElement CreateSchemaElement(string name, XmlQualifiedName schemaTypeName) { XmlSchemaElement element = new XmlSchemaElement(); element.Name = name; element.SchemaTypeName = schemaTypeName; return element; } /// /// Constructs an XmlSchemaAttribute and initialize it with the given parameters /// /// The attribute name /// Type enumeration for the attribute /// Whether the attribute is required or optional /// A new XmlSchemaAttribute object static XmlSchemaAttribute CreateSchemaAttribute(string name, ScriptSchemaStandardType schemaType, XmlSchemaUse use) { return CreateSchemaAttribute(name, GetQualifiedTypeName(schemaType), use); } /// /// Constructs an XmlSchemaAttribute and initialize it with the given parameters /// /// The attribute name /// Qualified name of the type for this attribute /// Whether the attribute is required or optional /// The new attribute static XmlSchemaAttribute CreateSchemaAttribute(string name, XmlQualifiedName schemaTypeName, XmlSchemaUse use) { XmlSchemaAttribute attribute = new XmlSchemaAttribute(); attribute.Name = name; attribute.SchemaTypeName = schemaTypeName; attribute.Use = use; return attribute; } /// /// Creates a simple type that is the union of two other types /// /// The name of the type /// List of valid types for the union /// A simple type which will match the given pattern static XmlSchemaSimpleType CreateSimpleTypeFromUnion(string name, params XmlSchemaType[] validTypes) { XmlSchemaSimpleTypeUnion union = new XmlSchemaSimpleTypeUnion(); foreach (XmlSchemaType validType in validTypes) { union.BaseTypes.Add(validType); } XmlSchemaSimpleType unionType = new XmlSchemaSimpleType(); unionType.Name = name; unionType.Content = union; return unionType; } /// /// Creates a simple type that matches a regex /// /// Name of the new type /// Regex pattern to match /// A simple type which will match the given pattern static XmlSchemaSimpleType CreateSimpleTypeFromRegex(string? name, string pattern) { XmlSchemaPatternFacet patternFacet = new XmlSchemaPatternFacet(); patternFacet.Value = pattern; XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction(); restriction.BaseTypeName = s_stringTypeName; restriction.Facets.Add(patternFacet); XmlSchemaSimpleType simpleType = new XmlSchemaSimpleType(); simpleType.Name = name; simpleType.Content = restriction; return simpleType; } /// /// Create a schema type for the given user type. Currently only handles enumerations. /// /// Name for the new type /// CLR type information to create a schema type for static XmlSchemaType CreateUserType(string name, Type type) { if (type.IsEnum) { return CreateSimpleTypeFromUnion(name, CreateEnumType(null, type), CreateSimpleTypeFromRegex(null, StringWithPropertiesPattern)); } else { throw new Exception($"Cannot create custom type in schema for '{type.Name}'"); } } /// /// Create a schema type for the given enum. /// /// Name for the new type /// CLR type information to create a schema type for static XmlSchemaType CreateEnumType(string? name, Type type) { XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction(); restriction.BaseTypeName = s_stringTypeName; foreach (string enumName in Enum.GetNames(type)) { XmlSchemaEnumerationFacet facet = new XmlSchemaEnumerationFacet(); facet.Value = enumName; restriction.Facets.Add(facet); } XmlSchemaSimpleType schemaType = new XmlSchemaSimpleType(); schemaType.Name = name; schemaType.Content = restriction; return schemaType; } } }