Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,132 @@ namespace DocumentFormat.OpenXml.Generator.Generators.Elements;

public static class DataModelWriterExtensions
{
// Use this dictionary to add attributes like ObsoleteAttribute or other directives to classes, child elements or attributes.
private static readonly Dictionary<string, Dictionary<string, List<string>>> _attributeData =
new Dictionary<string, Dictionary<string, List<string>>>()
{
// Example with annotations:
// {
// This is the containing complex type class, in the json metadata, this comes from the fully qualified "Name": "c:CT_BubbleSer/c15:ser",
// "c:CT_BubbleSer/c15:ser",
// new Dictionary<string, List<string>>()
// {
// {
// This is an example of obsoleting the whole class.
// In the json metadata:
// Use the same fully qualified name as the class, for example "Name": "c:CT_BubbleSer/c15:ser",
// "c:CT_BubbleSer/c15:ser",
// new List<string>()
// {
// "[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
// "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
// }
// },
// {
// This is an example obsoleting a child element (property in C#)
// In the json metadata:
// For child elements, this comes from "Name": "c:CT_PictureOptions/c:pictureOptions",
// "c:CT_PictureOptions/c:pictureOptions",
// new List<string>()
// {
// "[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
// "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
// }
// },
// {
// This is an example obsoleting a child attribute (property in C#)
// In the json metadata: use for example "QName": ":formatCode",
// ":formatCode",
// new List<string>()
// {
// "[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
// "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
// }
// },
// }
// },
{
"c:CT_BubbleSer/c15:ser",
new Dictionary<string, List<string>>()
{
{
"c:CT_PictureOptions/c:pictureOptions",
new List<string>()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are duplicated, so it may be nice to have a readonly static list that can be reused

{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
}
},
{
"c:CT_LineSer/c15:ser",
new Dictionary<string, List<string>>()
{
{
"c:CT_PictureOptions/c:pictureOptions",
new List<string>()
{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
}
},
{
"c:CT_PieSer/c15:ser",
new Dictionary<string, List<string>>()
{
{
"c:CT_PictureOptions/c:pictureOptions",
new List<string>()
{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
}
},
{
"c:CT_RadarSer/c15:ser",
new Dictionary<string, List<string>>()
{
{
"c:CT_PictureOptions/c:pictureOptions",
new List<string>()
{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
}
},
{
"c:CT_SurfaceSer/c15:ser",
new Dictionary<string, List<string>>()
{
{
"c:CT_PictureOptions/c:pictureOptions",
new List<string>()
{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
{
"c:CT_Boolean/c:bubble3D",
new List<string>()
{
"[Obsolete(\"Unused property, will be removed in the next major version.\", false)]",
"[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ",
}
},
}
},
};

private static string _elementAttributeStrings = string.Empty;

public static bool GetDataModelSyntax(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaNamespace model)
{
foreach (var ns in GetNamespaces(model, services).Distinct().OrderBy(n => n))
Expand Down Expand Up @@ -66,6 +192,20 @@ private static string GetBaseName(SchemaType type)
private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType element)
{
writer.WriteDocumentationComment(BuildTypeComments(services, element));

if (_attributeData.TryGetValue(element.Name.ToString(), out Dictionary<string, List<string>> ctAttributeData))
{
// if the fully qualified CT/tag name is also one of the children of the dictionary that means the attributes of that
// child's list need to be applied to the whole class, for example, if we're obsoleting an entire class.
if (ctAttributeData.TryGetValue(element.Name.ToString(), out List<string> attributeStrings))
{
foreach (string attributeString in attributeStrings)
{
writer.WriteLine(attributeString);
}
}
}

writer.Write("public ");

if (element.IsAbstract)
Expand Down Expand Up @@ -100,7 +240,16 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
foreach (var attribute in element.Attributes)
{
delimiter.AddDelimiter();
writer.WriteAttributeProperty(services, attribute);

if (_attributeData.TryGetValue(element.Name.ToString(), out Dictionary<string, List<string>> attrAttributeData)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could make the dictionary have the type of element.Name (I think it's a TypedQName) and it'll make it a bit more performant. The keys you're creating will also automatically be converted to it as well

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, that was a good idea. for SchemaAttributes, they aren't actually TypedQName but I decided to try using the Type property of the attribute metadata to construct a string that can convert to a TypedQName for the purposes of keys in the dictionary. It was either that or string.Empty which would have issues in parsing. So even though the Type property of the attribute metadata is actually the c# type (class), it works. If you have an alternative suggestion I'll try that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not to have the C# type class - it would be nice to have that a completely separate thing.

&& attrAttributeData.TryGetValue(attribute.QName.ToString(), out List<string> attrAttributeStrings))
{
writer.WriteAttributeProperty(services, attribute, attrAttributeStrings);
}
else
{
writer.WriteAttributeProperty(services, attribute);
}
}

delimiter.AddDelimiter();
Expand All @@ -110,7 +259,15 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
{
foreach (var node in element.Children)
{
writer.WriteElement(services, element, node, ref delimiter);
if (_attributeData.TryGetValue(element.Name.ToString(), out Dictionary<string, List<string>> childAttributeData)
&& childAttributeData.TryGetValue(node.Name.ToString(), out List<string> childAttributeStrings))
{
writer.WriteElement(services, element, node, ref delimiter, childAttributeStrings);
}
else
{
writer.WriteElement(services, element, node, ref delimiter);
}
}
}

Expand Down Expand Up @@ -298,7 +455,7 @@ void WriteUnion(IndentedTextWriter writer, string name, IEnumerable<Validator> v
}
}

private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter)
private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter, List<string>? attributeStrings = null)
{
if (string.IsNullOrEmpty(element.PropertyName))
{
Expand All @@ -320,6 +477,14 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
Remarks = $"xmlns:{element.Name.QName.Prefix} = {services.GetNamespaceInfo(element.Name.QName.Prefix).Uri}",
});

if (attributeStrings is not null)
{
foreach (string attributeString in attributeStrings)
{
writer.WriteLine(attributeString);
}
}

writer.Write("public ");
writer.Write(className);
writer.Write("? ");
Expand All @@ -335,7 +500,7 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
}
}

private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute)
private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute, List<string>? attributeStrings = null)
{
var remarks = default(string);
var info = services.GetNamespaceInfo(attribute.QName.Prefix);
Expand All @@ -359,6 +524,14 @@ private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenX
Remarks = remarks,
});

if (attributeStrings is not null)
{
foreach (string attributeString in attributeStrings)
{
writer.WriteLine(attributeString);
}
}

writer.Write("public ");
writer.Write(attribute.Type);
writer.Write("? ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2542,6 +2542,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.Marker? Marker
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.PictureOptions>();
Expand Down Expand Up @@ -3034,6 +3036,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.PictureOptions>();
Expand Down Expand Up @@ -3220,6 +3224,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.PictureOptions>();
Expand Down Expand Up @@ -3394,6 +3400,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.PictureOptions>();
Expand Down Expand Up @@ -3562,6 +3570,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.PictureOptions>();
Expand Down Expand Up @@ -3601,6 +3611,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.Values? Values
/// <remarks>
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
/// </remarks>
[Obsolete("Unused property, will be removed in the next major version.", false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public DocumentFormat.OpenXml.Drawing.Charts.Bubble3D? Bubble3D
{
get => GetElement<DocumentFormat.OpenXml.Drawing.Charts.Bubble3D>();
Expand Down
Loading