Exemple #1
0
        /// <summary>
        /// Writes the XML attribues as YAML.
        /// </summary>
        private static void WriteAttributes(YamlFormatArgs args, ConfigType ct, ConfigurationEntity ce, Type type, XElement xml)
        {
            var needsComma = false;

            foreach (var att in xml.Attributes())
            {
                var jname = XmlYamlTranslate.GetYamlName(ct, ce, att.Name.LocalName);
                var pi    = type.GetProperty(StringConversion.ToPascalCase(jname) !);
                var val   = XmlYamlTranslate.GetYamlValue(ct, ce, att.Name.LocalName, att.Value);
                if (val == null)
                {
                    continue;
                }

                if (pi == null || pi.GetCustomAttribute <JsonPropertyAttribute>() == null)
                {
                    jname = att.Name.LocalName;
                    args.UnknownAttributes.Add($"{xml.Name.LocalName}.{jname} = {val}");
                }

                if (needsComma)
                {
                    args.Writer.Write(", ");
                }

                args.HasAttributes = true;
                args.Writer.Write($"{jname}: {val}");

                if (args.Indent > 0)
                {
                    needsComma = true;
                }
                else
                {
                    args.Writer.WriteLine();
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Writes the schema for the object.
        /// </summary>
        private static void WriteObject(ConfigType ct, Type type, XNamespace ns, XElement xe, bool isRoot)
        {
            var csa = type.GetCustomAttribute <ClassSchemaAttribute>();

            if (csa == null)
            {
                throw new InvalidOperationException($"Type '{type.Name}' does not have a required ClassSchemaAttribute.");
            }

            if (!Enum.TryParse <ConfigurationEntity>(csa.Name, out var ce))
            {
                ce = ConfigurationEntity.CodeGen;
            }

            var xml = new XElement(ns + "element");

            xml.Add(new XAttribute("name", csa.Name));
            if (!isRoot)
            {
                xml.Add(new XAttribute("minOccurs", "0"));
                xml.Add(new XAttribute("maxOccurs", "unbounded"));
            }

            xml.Add(new XElement(ns + "annotation", new XElement(ns + "documentation", csa.Title)));
            var xct = new XElement(ns + "complexType");

            // Add sub-collections within xs:choice element.
            var hasSeq = false;
            var xs     = new XElement(ns + "choice");

            xs.Add(new XAttribute("maxOccurs", "unbounded"));
            foreach (var pi in type.GetProperties())
            {
                var pcsa = pi.GetCustomAttribute <PropertyCollectionSchemaAttribute>();
                if (pcsa == null)
                {
                    continue;
                }

                // Properties with List<string> are not compatible with XML and should be picked up as comma separated strings.
                if (pi.PropertyType == typeof(List <string>))
                {
                    continue;
                }

                WriteObject(ct, ComplexTypeReflector.GetItemType(pi.PropertyType), ns, xs, false);
                hasSeq = true;
            }

            if (hasSeq)
            {
                xct.Add(xs);
            }

            // Add properties as xs:attribute's.
            foreach (var pi in type.GetProperties())
            {
                var jpa = pi.GetCustomAttribute <JsonPropertyAttribute>();
                if (jpa == null)
                {
                    continue;
                }

                var name        = jpa.PropertyName ?? StringConversion.ToCamelCase(pi.Name) !;
                var xmlName     = XmlYamlTranslate.GetXmlName(ct, ce, name);
                var xmlOverride = XmlYamlTranslate.GetXmlPropertySchemaAttribute(ct, ce, xmlName);

                var psa = xmlOverride.Attribute ?? pi.GetCustomAttribute <PropertySchemaAttribute>();
                if (psa == null)
                {
                    // Properties with List<string> are not compatible with XML and should be picked up as comma separated strings.
                    if (pi.PropertyType == typeof(List <string>))
                    {
                        var pcsa = pi.GetCustomAttribute <PropertyCollectionSchemaAttribute>();
                        if (pcsa == null)
                        {
                            continue;
                        }

                        var xpx = new XElement(ns + "attribute",
                                               new XAttribute("name", xmlName),
                                               new XAttribute("use", pcsa.IsMandatory ? "required" : "optional"));

                        xpx.Add(new XElement(ns + "annotation", new XElement(ns + "documentation", GetDocumentation(name, pcsa))));
                        xct.Add(xpx);
                    }

                    continue;
                }

                var xp = new XElement(ns + "attribute",
                                      new XAttribute("name", xmlName),
                                      new XAttribute("use", psa.IsMandatory ? "required" : "optional"));

                xp.Add(new XElement(ns + "annotation", new XElement(ns + "documentation", GetDocumentation(name, psa))));

                if (psa.Options == null)
                {
                    xp.Add(new XAttribute("type", GetXmlType(pi, xmlOverride.Type)));
                }
                else
                {
                    var xr = new XElement(ns + "restriction", new XAttribute("base", GetXmlType(pi, xmlOverride.Type)));
                    foreach (var opt in psa.Options)
                    {
                        xr.Add(new XElement(ns + "enumeration", new XAttribute("value", opt)));
                    }

                    xp.Add(new XElement(ns + "simpleType", xr));
                }

                xct.Add(xp);
            }

            // Add this type into the overall document.
            xml.Add(xct);
            xe.Add(xml);
        }
Exemple #3
0
        /// <summary>
        /// Writes the markdown for the object.
        /// </summary>
        private static void WriteObject(string path, ConfigType ct, Type type, bool isYaml)
        {
            var csa = type.GetCustomAttribute <ClassSchemaAttribute>();

            if (csa == null)
            {
                return;
            }

            if (!Enum.TryParse <ConfigurationEntity>(csa.Name, out var ce))
            {
                ce = ConfigurationEntity.CodeGen;
            }

            var fn = Path.Combine(path, $"{ct}-{csa.Name}-{(isYaml ? "Config" : "Config-Xml")}.md");

            Beef.Diagnostics.Logger.Default.LogWarning($" > Creating: {fn}");
            using var sw = File.CreateText(fn);

            var pdlist = new List <PropertyData>();

            foreach (var pi in type.GetProperties())
            {
                var jpa = pi.GetCustomAttribute <JsonPropertyAttribute>();
                if (jpa == null)
                {
                    continue;
                }

                var pd = new PropertyData
                {
                    Name     = jpa.PropertyName ?? StringConversion.ToCamelCase(pi.Name),
                    Property = pi,
                    Psa      = pi.GetCustomAttribute <PropertySchemaAttribute>()
                };

                if (!isYaml)
                {
                    pd.Name = XmlYamlTranslate.GetXmlName(ct, ce, pd.Name !);
                    var xpsa = XmlYamlTranslate.GetXmlPropertySchemaAttribute(ct, ce, pd.Name).Attribute;
                    if (xpsa != null)
                    {
                        pd.Psa = xpsa;
                    }
                }

                if (pd.Psa == null)
                {
                    pd.Pcsa = pi.GetCustomAttribute <PropertyCollectionSchemaAttribute>();
                    if (pd.Pcsa == null)
                    {
                        throw new InvalidOperationException($"Type '{type.Name}' Property '{pi.Name}' does not have a required PropertySchemaAttribute or PropertyCollectionSchemaAttribute.");
                    }

                    pd.Category = pd.Pcsa.Category;
                }
                else
                {
                    pd.Category = pd.Psa.Category;
                }

                pdlist.Add(pd);
            }

            sw.WriteLine($"# {csa.Title} - {(isYaml ? "YAML/JSON" : "XML")}");
            sw.WriteLine();
            sw.WriteLine(csa.Description);
            if (!string.IsNullOrEmpty(csa.Markdown))
            {
                sw.WriteLine();
                sw.WriteLine(csa.Markdown);
            }

            sw.WriteLine();
            sw.WriteLine("<br/>");
            sw.WriteLine();

            if (isYaml && !string.IsNullOrEmpty(csa.ExampleMarkdown))
            {
                sw.WriteLine("## Example");
                sw.WriteLine();
                sw.WriteLine(csa.ExampleMarkdown);
                sw.WriteLine();
                sw.WriteLine("<br/>");
                sw.WriteLine();
            }

            var cats = type.GetCustomAttributes <CategorySchemaAttribute>();

            if (cats.Count() > 1)
            {
                sw.WriteLine("## Property categories");
                sw.WriteLine($"The `{csa.Name}` object supports a number of properties that control the generated code output. These properties are separated into a series of logical categories. The properties with a bold name are those that are more typically used (considered more important).");
                sw.WriteLine();
                sw.WriteLine("Category | Description");
                sw.WriteLine("-|-");

                foreach (var cat in cats)
                {
                    sw.WriteLine($"[`{cat.Category}`](#{cat.Category}) | {cat.Title}");
                }

                sw.WriteLine();
                sw.WriteLine("<br/>");
                sw.WriteLine();
            }
            else
            {
                sw.WriteLine("## Properties");
                sw.WriteLine($"The `{csa.Name}` object supports a number of properties that control the generated code output. The properties with a bold name are those that are more typically used (considered more important).");
                sw.WriteLine();
            }

            foreach (var cat in cats)
            {
                if (cats.Count() > 1)
                {
                    sw.WriteLine($"## {cat.Category}");
                    sw.Write(cat.Title);
                    if (cat.Description != null)
                    {
                        sw.Write($" {cat.Description}");
                    }

                    sw.WriteLine();
                    sw.WriteLine();
                }

                sw.WriteLine("Property | Description");
                sw.WriteLine("-|-");

                foreach (var p in pdlist.Where(x => x.Category == cat.Category))
                {
                    if (p.Psa != null)
                    {
                        WriteTableItem(sw, p.Name, p.Psa.Title, p.Psa.Description, null, p.Psa.IsImportant, p.Psa.Options);
                    }
                    else
                    {
                        var pt    = ComplexTypeReflector.GetItemType(p.Property !.PropertyType);
                        var ptcsa = pt.GetCustomAttribute <ClassSchemaAttribute>() !;
                        if (ptcsa != null)
                        {
                            WriteTableItem(sw, p.Name, $"The corresponding [`{ptcsa.Name}`]({ct}-{ptcsa.Name}-{(isYaml ? "Config" : "Config-Xml")}.md) collection.", p.Pcsa !.Description, p.Pcsa.Markdown, p.Pcsa.IsImportant);
                        }
                        else if (p.Pcsa != null)
                        {
                            WriteTableItem(sw, p.Name, p.Pcsa.Title, p.Pcsa.Description, p.Pcsa.Markdown, p.Pcsa.IsImportant);
                        }
                    }
                }

                sw.WriteLine();
                sw.WriteLine("<br/>");
                sw.WriteLine();
            }

            sw.WriteLine("<sub><sup>Note: This markdown file is generated; any changes will be lost.</sup></sub>");

            // Done, close file, then move onto children.
            sw.Close();

            foreach (var p in pdlist.Where(x => x.Pcsa != null))
            {
                WriteObject(path, ct, ComplexTypeReflector.GetItemType(p.Property !.PropertyType), isYaml);
            }
        }