/// <summary> /// Parses schema set annotations and captures the sce.domgen annotation XmlNodes /// to a dictionary indext by type name</summary> /// <param name="schemaSet">Xml schema set</param> /// <param name="annotations">Local dictionary to write annotations to. /// This is NOT the same as the DomGenAnnotations dictionary.</param> protected override void ParseAnnotations(XmlSchemaSet schemaSet, IDictionary <NamedMetadata, IList <XmlNode> > annotations) { base.ParseAnnotations(schemaSet, annotations); DomGenAnnotations = new Dictionary <string, NodeAnnotationInfo>(); foreach (var annotation in annotations) { string typeName = annotation.Key.Name; foreach (XmlNode xmlNode in annotation.Value) { NodeAnnotationInfo annotationInfo = new NodeAnnotationInfo(); DomGenAnnotations.TryGetValue(typeName, out annotationInfo); if (xmlNode.Name == "sce.domgen") { foreach (XmlAttribute attribute in xmlNode.Attributes) { if (attribute.Name == "include") { annotationInfo.DomgenInclude = Boolean.Parse(attribute.Value); // will throw if value is not a valid boolean } } } DomGenAnnotations[typeName] = annotationInfo; } } }
/// <summary> /// Generates the Schema CSharp class</summary> /// <param name="typeLoader">Type loader with loaded type and annotation information</param> /// <param name="schemaNamespace">Target namespace of the schema</param> /// <param name="codeNamespace">Namespace of the class ot be generated</param> /// <param name="className">Name of the class to be generated</param> /// <param name="args">Commandline arguments</param> /// <returns>CSharp Schema class as string</returns> public static string Generate(SchemaLoader typeLoader, string schemaNamespace, string codeNamespace, string className, string[] args) { bool generateAdapters = false; bool annotatedOnly = false; bool generateEnums = false; for (int i = 4; i < args.Length; i++) { string arg = args[i]; if (arg == "-a" || arg == "-adapters") { generateAdapters = true; } else if (arg == "-annotatedOnly") { annotatedOnly = true; } else if (arg == "-enums") { generateEnums = true; } } XmlSchemaTypeCollection typeCollection = GetTypeCollection(typeLoader, schemaNamespace); string targetNamespace = typeCollection.TargetNamespace; XmlQualifiedName[] namespaces = typeCollection.Namespaces; List <DomNodeType> nodeTypes = new List <DomNodeType>(typeCollection.GetNodeTypes()); // Append additional DomNodeTypes from other namespaces, for example if the xs:import was used. // Don't include the built-in "anyType". // The reason to append is that if there is a conflict with the imported types, priority should // be given to the types defined in the importing schema file. foreach (XmlQualifiedName knownNamespace in namespaces) { if (knownNamespace.Namespace != targetNamespace && knownNamespace.Namespace != "http://www.w3.org/2001/XMLSchema") { nodeTypes.AddRange(typeCollection.GetNodeTypes(knownNamespace.Namespace)); } } List <ChildInfo> rootElements = new List <ChildInfo>(typeCollection.GetRootElements()); StringBuilder sb = new StringBuilder(); GenerateFileProlog(codeNamespace, args, sb); WriteLine(sb, " public static class {0}", className); WriteLine(sb, " {{"); WriteLine(sb, " public const string NS = \"{0}\";", targetNamespace); WriteLine(sb, ""); WriteLine(sb, " public static void Initialize(XmlSchemaTypeCollection typeCollection)"); WriteLine(sb, " {{"); WriteLine(sb, " Initialize((ns,name)=>typeCollection.GetNodeType(ns,name),"); WriteLine(sb, " (ns,name)=>typeCollection.GetRootElement(ns,name));"); WriteLine(sb, " }}"); WriteLine(sb, ""); WriteLine(sb, " public static void Initialize(IDictionary<string, XmlSchemaTypeCollection> typeCollections)"); WriteLine(sb, " {{"); WriteLine(sb, " Initialize((ns,name)=>typeCollections[ns].GetNodeType(name),"); WriteLine(sb, " (ns,name)=>typeCollections[ns].GetRootElement(name));"); WriteLine(sb, " }}"); WriteLine(sb, ""); WriteLine(sb, " private static void Initialize(Func<string, string, DomNodeType> getNodeType, Func<string, string, ChildInfo> getRootElement)"); WriteLine(sb, " {{"); StringBuilder fieldSb = new StringBuilder(); Dictionary <string, string> domNodeTypeToClassName = new Dictionary <string, string>(nodeTypes.Count); Dictionary <string, string> classNameToDomNodeType = new Dictionary <string, string>(nodeTypes.Count); foreach (DomNodeType nodeType in nodeTypes) { NodeAnnotationInfo annotationInfo = new NodeAnnotationInfo(); typeLoader.DomGenAnnotations.TryGetValue(nodeType.Name, out annotationInfo); // Determine if the type should be included or skipped // If the -annotatedOnly argument is set: types will be included // ONLY IF <sce.domgen include="true"> is defined for this type, all other types will be skipped // If -annotatedOnly is NOT set: types will be included by default // UNLESS <sce.domgen include="false" is explicitly set for this type bool include = !annotatedOnly || annotationInfo.DomgenInclude; if (!include) { continue; // skip this type if it's not to be included } string ns = codeNamespace; if (ns == null) { ns = targetNamespace; } string typeName = GetClassName(namespaces, nodeType, domNodeTypeToClassName, classNameToDomNodeType); GenerateInitializers(nodeType, typeName, sb); WriteLine(sb, ""); WriteLine(fieldSb, ""); GenerateFields(nodeType, typeName, fieldSb); } if (generateEnums) { GenerateEnums(fieldSb, typeLoader, namespaces, domNodeTypeToClassName, classNameToDomNodeType); } foreach (ChildInfo rootElement in rootElements) { string fieldName = rootElement.Name + "RootElement"; WriteLine(fieldSb, ""); WriteLine(fieldSb, " public static ChildInfo {0};", fieldName); WriteLine(sb, " {0} = getRootElement(NS, \"{1}\");", fieldName, rootElement.Name); } WriteLine(sb, " }}"); sb.Append(fieldSb.ToString()); WriteLine(sb, " }}"); if (generateAdapters) { WriteLine(sb, ""); foreach (DomNodeType nodeType in nodeTypes) { string modifiers = (nodeType.IsAbstract) ? "abstract " : ""; string adapterClassName = GetClassName(nodeType, domNodeTypeToClassName); string adapterBaseClassName = "DomNodeAdapter"; if (nodeType.BaseType != DomNodeType.BaseOfAllTypes) { adapterBaseClassName = GetClassName(nodeType.BaseType, domNodeTypeToClassName); } WriteLine(sb, " public {0}partial class {1} : {2}", modifiers, adapterClassName, adapterBaseClassName); WriteLine(sb, " {{"); foreach (AttributeInfo attrInfo in nodeType.Attributes) { if (attrInfo.DefiningType != nodeType) { continue; } string typeName = attrInfo.Type.Type.ToString(); typeName = s_attributeTypes[typeName]; string attrName = attrInfo.Name; string propertyName = attrName; if (s_cSharpKeywords.Contains(propertyName)) { propertyName = "@" + propertyName; } WriteLine(sb, " public {0} {1}", typeName, propertyName); WriteLine(sb, " {{"); string attrInfoName = className + "." + adapterClassName + "." + attrName + "Attribute"; WriteLine(sb, " get {{ return GetAttribute<{0}>({1}); }}", typeName, attrInfoName); WriteLine(sb, " set {{ SetAttribute({0}, value); }}", attrInfoName); WriteLine(sb, " }}"); } foreach (ChildInfo childInfo in nodeType.Children) { if (childInfo.DefiningType != nodeType) { continue; } string childName = childInfo.Name; string propertyName = childName; string typeName = GetClassName(childInfo.Type, domNodeTypeToClassName); string childInfoName = className + "." + adapterClassName + "." + childName + "Child"; if (childInfo.IsList) { WriteLine(sb, " public IList<{0}> {1}", typeName, propertyName); WriteLine(sb, " {{"); WriteLine(sb, " get {{ return GetChildList<{0}>({1}); }}", typeName, childInfoName); WriteLine(sb, " }}"); } else { WriteLine(sb, " public {0} {1}", typeName, propertyName); WriteLine(sb, " {{"); WriteLine(sb, " get {{ return GetChild<{0}>({1}); }}", typeName, childInfoName); WriteLine(sb, " set {{ SetChild({0}, value); }}", childInfoName); WriteLine(sb, " }}"); } } WriteLine(sb, " }}"); WriteLine(sb, ""); } } GenerateFileEpilog(sb); return(sb.ToString()); }