@@ -11,6 +11,112 @@ namespace DocumentFormat.OpenXml.Generator.Generators.Elements;
1111
1212public static class DataModelWriterExtensions
1313{
14+ public static class AttributeStrings
15+ {
16+ public const string ObsoletePropertyWarn = "[Obsolete(\" Unused property, will be removed in a future version.\" , false)]" ;
17+ public const string ObsoletePropertyError = "[Obsolete(\" Unused property, will be removed in a future version.\" , true)]" ;
18+ public const string ObsoleteAttributeWarn = "[Obsolete(\" Unused attribute, will be removed in a future version.\" , false)]" ;
19+ public const string ObsoleteAttributeError = "[Obsolete(\" Unused attribute, will be removed in a future version.\" , true)]" ;
20+ public const string EditorBrowsableAlways = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always)] " ;
21+ public const string EditorBrowsableAdvanced = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] " ;
22+ public const string EditorBrowsableNever = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] " ;
23+ }
24+
25+ private static readonly List < string > ObsoletePropertyWarnList =
26+ [
27+ AttributeStrings . ObsoletePropertyWarn ,
28+ AttributeStrings . EditorBrowsableNever ,
29+ ] ;
30+
31+ // Use this dictionary to add attributes like ObsoleteAttribute or other directives to classes, child elements or attributes.
32+ private static readonly Dictionary < TypedQName , Dictionary < TypedQName , List < string > > > _attributeData =
33+ new Dictionary < TypedQName , Dictionary < TypedQName , List < string > > > ( )
34+ {
35+ // Example with annotations:
36+ // {
37+ // This is the containing complex type class, in the json metadata, this comes from the fully qualified "Name": "c:CT_BubbleSer/c15:ser",
38+ // "c:CT_BubbleSer/c15:ser",
39+ // new Dictionary<TypedQName, List<string>>()
40+ // {
41+ // {
42+ // This is an example of obsoleting the whole class.
43+ // In the json metadata:
44+ // Use the same fully qualified name as the class, for example "Name": "c:CT_BubbleSer/c15:ser",
45+ // "c:CT_BubbleSer/c15:ser",
46+ // ObsoleteClassErrorList
47+ // },
48+ // {
49+ // This is an example obsoleting a child element (property in C#)
50+ // In the json metadata:
51+ // For child elements, this comes from "Name": "c:CT_PictureOptions/c:pictureOptions",
52+ // "c:CT_PictureOptions/c:pictureOptions",
53+ // ObsoletePropertyWarnList
54+ // },
55+ // {
56+ // This is an example obsoleting a child attribute (property in C#)
57+ // In the json metadata: use for example "QName" converted to a TypedQName string using the C# type from the
58+ // Type property with no prefix: ":StringValue/:formatCode",
59+ // ":StringValue/:formatCode",
60+ // ObsoleteAttributeWarnList
61+ // },
62+ // }
63+ // },
64+ {
65+ "c:CT_BubbleSer/c15:ser" ,
66+ new Dictionary < TypedQName , List < string > > ( )
67+ {
68+ {
69+ "c:CT_PictureOptions/c:pictureOptions" ,
70+ ObsoletePropertyWarnList
71+ } ,
72+ }
73+ } ,
74+ {
75+ "c:CT_LineSer/c15:ser" ,
76+ new Dictionary < TypedQName , List < string > > ( )
77+ {
78+ {
79+ "c:CT_PictureOptions/c:pictureOptions" ,
80+ ObsoletePropertyWarnList
81+ } ,
82+ }
83+ } ,
84+ {
85+ "c:CT_PieSer/c15:ser" ,
86+ new Dictionary < TypedQName , List < string > > ( )
87+ {
88+ {
89+ "c:CT_PictureOptions/c:pictureOptions" ,
90+ ObsoletePropertyWarnList
91+ } ,
92+ }
93+ } ,
94+ {
95+ "c:CT_RadarSer/c15:ser" ,
96+ new Dictionary < TypedQName , List < string > > ( )
97+ {
98+ {
99+ "c:CT_PictureOptions/c:pictureOptions" ,
100+ ObsoletePropertyWarnList
101+ } ,
102+ }
103+ } ,
104+ {
105+ "c:CT_SurfaceSer/c15:ser" ,
106+ new Dictionary < TypedQName , List < string > > ( )
107+ {
108+ {
109+ "c:CT_PictureOptions/c:pictureOptions" ,
110+ ObsoletePropertyWarnList
111+ } ,
112+ {
113+ "c:CT_Boolean/c:bubble3D" ,
114+ ObsoletePropertyWarnList
115+ } ,
116+ }
117+ } ,
118+ } ;
119+
14120 public static bool GetDataModelSyntax ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaNamespace model )
15121 {
16122 foreach ( var ns in GetNamespaces ( model , services ) . Distinct ( ) . OrderBy ( n => n ) )
@@ -66,6 +172,20 @@ private static string GetBaseName(SchemaType type)
66172 private static void WriteType ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaType element )
67173 {
68174 writer . WriteDocumentationComment ( BuildTypeComments ( services , element ) ) ;
175+
176+ if ( _attributeData . TryGetValue ( element . Name , out Dictionary < TypedQName , List < string > > ctAttributeData ) )
177+ {
178+ // if the fully qualified CT/tag name is also one of the children of the dictionary that means the attributes of that
179+ // child's list need to be applied to the whole class, for example, if we're obsoleting an entire class.
180+ if ( ctAttributeData . TryGetValue ( element . Name , out List < string > attributeStrings ) )
181+ {
182+ foreach ( string attributeString in attributeStrings )
183+ {
184+ writer . WriteLine ( attributeString ) ;
185+ }
186+ }
187+ }
188+
69189 writer . Write ( "public " ) ;
70190
71191 if ( element . IsAbstract )
@@ -100,7 +220,16 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
100220 foreach ( var attribute in element . Attributes )
101221 {
102222 delimiter . AddDelimiter ( ) ;
103- writer . WriteAttributeProperty ( services , attribute ) ;
223+
224+ if ( _attributeData . TryGetValue ( element . Name , out Dictionary < TypedQName , List < string > > attrAttributeData )
225+ && attrAttributeData . TryGetValue ( ":" + attribute . Type + "/" + attribute . QName . ToString ( ) , out List < string > attrAttributeStrings ) )
226+ {
227+ writer . WriteAttributeProperty ( services , attribute , attrAttributeStrings ) ;
228+ }
229+ else
230+ {
231+ writer . WriteAttributeProperty ( services , attribute ) ;
232+ }
104233 }
105234
106235 delimiter . AddDelimiter ( ) ;
@@ -110,7 +239,15 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
110239 {
111240 foreach ( var node in element . Children )
112241 {
113- writer . WriteElement ( services , element , node , ref delimiter ) ;
242+ if ( _attributeData . TryGetValue ( element . Name , out Dictionary < TypedQName , List < string > > childAttributeData )
243+ && childAttributeData . TryGetValue ( node . Name , out List < string > childAttributeStrings ) )
244+ {
245+ writer . WriteElement ( services , element , node , ref delimiter , childAttributeStrings ) ;
246+ }
247+ else
248+ {
249+ writer . WriteElement ( services , element , node , ref delimiter ) ;
250+ }
114251 }
115252 }
116253
@@ -298,7 +435,7 @@ void WriteUnion(IndentedTextWriter writer, string name, IEnumerable<Validator> v
298435 }
299436 }
300437
301- private static void WriteElement ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaType parent , SchemaElement element , ref Delimiter delimiter )
438+ private static void WriteElement ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaType parent , SchemaElement element , ref Delimiter delimiter , List < string > ? attributeStrings = null )
302439 {
303440 if ( string . IsNullOrEmpty ( element . PropertyName ) )
304441 {
@@ -320,6 +457,14 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
320457 Remarks = $ "xmlns:{ element . Name . QName . Prefix } = { services . GetNamespaceInfo ( element . Name . QName . Prefix ) . Uri } ",
321458 } ) ;
322459
460+ if ( attributeStrings is not null )
461+ {
462+ foreach ( string attributeString in attributeStrings )
463+ {
464+ writer . WriteLine ( attributeString ) ;
465+ }
466+ }
467+
323468 writer . Write ( "public " ) ;
324469 writer . Write ( className ) ;
325470 writer . Write ( "? " ) ;
@@ -335,7 +480,7 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
335480 }
336481 }
337482
338- private static void WriteAttributeProperty ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaAttribute attribute )
483+ private static void WriteAttributeProperty ( this IndentedTextWriter writer , OpenXmlGeneratorServices services , SchemaAttribute attribute , List < string > ? attributeStrings = null )
339484 {
340485 var remarks = default ( string ) ;
341486 var info = services . GetNamespaceInfo ( attribute . QName . Prefix ) ;
@@ -359,6 +504,14 @@ private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenX
359504 Remarks = remarks ,
360505 } ) ;
361506
507+ if ( attributeStrings is not null )
508+ {
509+ foreach ( string attributeString in attributeStrings )
510+ {
511+ writer . WriteLine ( attributeString ) ;
512+ }
513+ }
514+
362515 writer . Write ( "public " ) ;
363516 writer . Write ( attribute . Type ) ;
364517 writer . Write ( "? " ) ;
0 commit comments