Example #1
0
        /// <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;
                }
            }
        }
Example #2
0
        /// <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());
        }