merge -r 53370:58178
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlTypeMapping.cs
1 //\r
2 // XmlTypeMapping.cs: \r
3 //\r
4 // Author:\r
5 //   John Donagher (john@webmeta.com)\r
6 //   Lluis Sanchez Gual (lluis@ximian.com)\r
7 //\r
8 // (C) 2002 John Donagher\r
9 //\r
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 \r
32 using System.Xml;\r
33 using System;\r
34 using System.Collections;\r
35 using System.Globalization;
36 using System.Xml.Schema;\r
37 \r
38 namespace System.Xml.Serialization\r
39 {\r
40         public class XmlTypeMapping : XmlMapping\r
41         {\r
42                 private string xmlType;\r
43                 private string xmlTypeNamespace;\r
44                 TypeData type;\r
45                 XmlTypeMapping baseMap;\r
46                 bool multiReferenceType = false;\r
47                 bool isSimpleType;\r
48                 string documentation;\r
49                 bool includeInSchema;\r
50                 bool isNullable = true;\r
51 \r
52                 ArrayList _derivedTypes = new ArrayList();\r
53 \r
54                 internal XmlTypeMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)\r
55                 : base (elementName, ns)\r
56                 {\r
57                         this.type = typeData;\r
58                         this.xmlType = xmlType;\r
59                         this.xmlTypeNamespace = xmlTypeNamespace;\r
60                 }\r
61 \r
62 #if !NET_2_0\r
63                 public string ElementName\r
64                 {\r
65                         get { return _elementName; }\r
66                 }\r
67 \r
68                 public string Namespace\r
69                 {\r
70                         get { return _namespace; }\r
71                 }\r
72 #endif\r
73 \r
74                 public string TypeFullName\r
75                 {\r
76                         get { return type.FullTypeName; }\r
77                 }\r
78 \r
79                 public string TypeName\r
80                 {\r
81                         get { return type.TypeName; }\r
82                 }\r
83 \r
84                 internal TypeData TypeData\r
85                 {\r
86                         get { return type; }\r
87                 }\r
88 \r
89                 internal string XmlType\r
90                 {\r
91                         get { return xmlType; }\r
92                 }\r
93 \r
94                 internal string XmlTypeNamespace\r
95                 {\r
96                         get { return xmlTypeNamespace; }\r
97                 }\r
98 \r
99                 internal ArrayList DerivedTypes\r
100                 {\r
101                         get { return _derivedTypes; }\r
102                         set { _derivedTypes = value; }\r
103                 }\r
104 \r
105                 internal bool MultiReferenceType\r
106                 {\r
107                         get { return multiReferenceType; }\r
108                         set { multiReferenceType = value; }\r
109                 }\r
110 \r
111                 internal XmlTypeMapping BaseMap\r
112                 {\r
113                         get { return baseMap; }\r
114                         set { baseMap = value; }\r
115                 }\r
116 \r
117                 internal bool IsSimpleType\r
118                 {\r
119                         get { return isSimpleType; }\r
120                         set { isSimpleType = value; }\r
121                 }\r
122 \r
123                 internal string Documentation\r
124                 {\r
125                         set { documentation = value; }\r
126                         get { return documentation; }\r
127                 }\r
128 \r
129                 internal bool IncludeInSchema\r
130                 {\r
131                         get { return includeInSchema; }\r
132                         set { includeInSchema = value; }\r
133                 }\r
134                 \r
135                 internal bool IsNullable\r
136                 {\r
137                         get { return isNullable; }\r
138                         set { isNullable = value; }\r
139                 }\r
140 \r
141                 internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
142                 {\r
143                         // Returns the map for a subtype of this map's type\r
144 \r
145                         objectFullTypeName = objectFullTypeName.Replace ('+','.');\r
146                         if (TypeFullName == objectFullTypeName) return this;\r
147                         for (int n=0; n<_derivedTypes.Count; n++) {\r
148                                 XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];\r
149                                 if (map.TypeFullName == objectFullTypeName) return map;\r
150                         }\r
151                         \r
152                         return null;\r
153                 }\r
154 \r
155                 internal XmlTypeMapping GetRealElementMap (string name, string ens)\r
156                 {\r
157                         if (xmlType == name && xmlTypeNamespace == ens) return this;\r
158                         foreach (XmlTypeMapping map in _derivedTypes)\r
159                                 if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;\r
160                         \r
161                         return null;\r
162                 }\r
163                 \r
164                 internal void UpdateRoot (XmlQualifiedName qname)\r
165                 {\r
166                         if (qname != null) {\r
167                                 this._elementName = qname.Name;\r
168                                 this._namespace = qname.Namespace;\r
169                         }\r
170                 }\r
171         }\r
172 \r
173  
174         // Mapping info for XmlSerializable
175         internal class XmlSerializableMapping : XmlTypeMapping
176         {
177                 XmlSchema _schema;
178
179                 internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
180                         : base(elementName, ns, typeData, xmlType, xmlTypeNamespace)
181                 {
182                         IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type);
183                         _schema = serializable.GetSchema();
184                         if (_schema != null) 
185                         {
186                                 if (_schema.Id == null || _schema.Id.Length == 0) 
187                                         throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id.");
188                         }
189                 }
190
191                 internal XmlSchema Schema
192                 {
193                         get { return _schema; }
194                 }
195         }
196  
197
198         // Mapping info for classes and structs\r
199 \r
200         internal class ClassMap: ObjectMap\r
201         {\r
202                 Hashtable _elements = new Hashtable ();\r
203                 ArrayList _elementMembers;\r
204                 Hashtable _attributeMembers;\r
205                 XmlTypeMapMemberAttribute[] _attributeMembersArray;\r
206                 XmlTypeMapElementInfo[] _elementsByIndex;\r
207                 ArrayList _flatLists;\r
208                 ArrayList _allMembers = new ArrayList ();\r
209                 ArrayList _membersWithDefault;\r
210                 ArrayList _listMembers;\r
211                 XmlTypeMapMemberAnyElement _defaultAnyElement;\r
212                 XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;\r
213                 XmlTypeMapMemberNamespaces _namespaceDeclarations;\r
214                 XmlTypeMapMember _xmlTextCollector;\r
215                 XmlTypeMapMember _returnMember;\r
216                 bool _ignoreMemberNamespace;\r
217                 bool _canBeSimpleType = true;\r
218 \r
219                 public void AddMember (XmlTypeMapMember member)\r
220                 {\r
221                         _allMembers.Add (member);\r
222                         \r
223                         if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {\r
224                                 if (_membersWithDefault == null) _membersWithDefault = new ArrayList ();\r
225                                 _membersWithDefault.Add (member);\r
226                         }\r
227                         \r
228                         if (member.IsReturnValue)\r
229                                 _returnMember = member;\r
230                         \r
231                         if (member is XmlTypeMapMemberAttribute)\r
232                         {\r
233                                 XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;\r
234                                 if (_attributeMembers == null) _attributeMembers = new Hashtable();\r
235                                 string key = BuildKey (atm.AttributeName, atm.Namespace);\r
236                                 if (_attributeMembers.ContainsKey (key))\r
237                                         throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");\r
238                                 member.Index = _attributeMembers.Count;\r
239                                 _attributeMembers.Add (key, member);\r
240                                 return;\r
241                         }\r
242                         else if (member is XmlTypeMapMemberFlatList)\r
243                         {\r
244                                 RegisterFlatList ((XmlTypeMapMemberFlatList)member);\r
245                         }\r
246                         else if (member is XmlTypeMapMemberAnyElement)\r
247                         {\r
248                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement) member;\r
249                                 if (mem.IsDefaultAny) _defaultAnyElement = mem;\r
250                                 if (mem.TypeData.IsListType) RegisterFlatList (mem);\r
251                         }\r
252                         else if (member is XmlTypeMapMemberAnyAttribute)\r
253                         {\r
254                                 _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute) member;\r
255                                 return;\r
256                         }\r
257                         else if (member is XmlTypeMapMemberNamespaces)\r
258                         {\r
259                                 _namespaceDeclarations = (XmlTypeMapMemberNamespaces) member;\r
260                                 return;\r
261                         }\r
262 \r
263                         if (member is XmlTypeMapMemberElement && ((XmlTypeMapMemberElement)member).IsXmlTextCollector)\r
264                         {\r
265                                 if (_xmlTextCollector != null) throw new InvalidOperationException ("XmlTextAttribute can only be applied once in a class");\r
266                                 _xmlTextCollector = member;\r
267                         }\r
268 \r
269                         if (_elementMembers == null) {\r
270                                 _elementMembers = new ArrayList();\r
271                                 _elements = new Hashtable();\r
272                         }\r
273 \r
274                         member.Index = _elementMembers.Count;\r
275                         _elementMembers.Add (member);\r
276 \r
277                         ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;\r
278                         foreach (XmlTypeMapElementInfo elem in elemsInfo)\r
279                         {\r
280                                 string key = BuildKey (elem.ElementName, elem.Namespace);\r
281                                 if (_elements.ContainsKey (key)) \r
282                                         throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");\r
283                                 _elements.Add (key, elem);\r
284                         }
285                         
286                         if (member.TypeData.IsListType && member.TypeData.Type != null && !member.TypeData.Type.IsArray) {
287                                 if (_listMembers == null) _listMembers = new ArrayList ();\r
288                                 _listMembers.Add (member);\r
289                         }\r
290                 }\r
291 \r
292                 void RegisterFlatList (XmlTypeMapMemberExpandable member)\r
293                 {\r
294                         if (_flatLists == null) _flatLists = new ArrayList ();\r
295                         member.FlatArrayIndex = _flatLists.Count;\r
296                         _flatLists.Add (member);\r
297                 }\r
298 \r
299                 public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)\r
300                 {\r
301                         if (_attributeMembers == null) return null;\r
302                         return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)];\r
303                 }\r
304 \r
305                 public XmlTypeMapElementInfo GetElement (string name, string ns)\r
306                 {\r
307                         if (_elements == null) return null;\r
308                         return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)];\r
309                 }\r
310                 \r
311                 public XmlTypeMapElementInfo GetElement (int index)\r
312                 {\r
313                         if (_elements == null) return null;\r
314                         \r
315                         if (_elementsByIndex == null)\r
316                         {\r
317                                 _elementsByIndex = new XmlTypeMapElementInfo [_elementMembers.Count];\r
318                                 foreach (XmlTypeMapMemberElement mem in _elementMembers)\r
319                                 {\r
320                                         if (mem.ElementInfo.Count != 1) \r
321                                                 throw new InvalidOperationException ("Read by order only possible for encoded/bare format");\r
322                                                 \r
323                                         _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];\r
324                                 }\r
325                         }\r
326                         \r
327                         return _elementsByIndex [index];\r
328                 }\r
329                 \r
330                 private string BuildKey (string name, string ns)\r
331                 {\r
332                         if (_ignoreMemberNamespace) return name;\r
333                         else return name + " / " + ns;\r
334                 }\r
335                 \r
336                 public ICollection AllElementInfos\r
337                 {\r
338                         get { return _elements.Values; }\r
339                 }\r
340                 \r
341                 \r
342                 public bool IgnoreMemberNamespace\r
343                 {\r
344                         get { return _ignoreMemberNamespace; }\r
345                         set { _ignoreMemberNamespace = value; }\r
346                 }\r
347 \r
348                 public XmlTypeMapMember FindMember (string name)\r
349                 {\r
350                         for (int n=0; n<_allMembers.Count; n++)\r
351                                 if (((XmlTypeMapMember)_allMembers[n]).Name == name) return (XmlTypeMapMember)_allMembers[n];\r
352                         return null;\r
353                 }\r
354 \r
355                 public XmlTypeMapMemberAnyElement DefaultAnyElementMember\r
356                 {\r
357                         get { return _defaultAnyElement; }\r
358                 }\r
359 \r
360                 public XmlTypeMapMemberAnyAttribute DefaultAnyAttributeMember\r
361                 {\r
362                         get { return _defaultAnyAttribute; }\r
363                 }\r
364 \r
365                 public XmlTypeMapMemberNamespaces NamespaceDeclarations\r
366                 {\r
367                         get { return _namespaceDeclarations; }\r
368                 }\r
369 \r
370                 public ICollection AttributeMembers\r
371                 {\r
372                         get \r
373                         {\r
374                                 if (_attributeMembers == null) return null;\r
375                                 if (_attributeMembersArray != null) return _attributeMembersArray;\r
376                                 \r
377                                 _attributeMembersArray = new XmlTypeMapMemberAttribute[_attributeMembers.Count];\r
378                                 foreach (XmlTypeMapMemberAttribute mem in _attributeMembers.Values)\r
379                                         _attributeMembersArray [mem.Index] = mem;\r
380                                 return _attributeMembersArray;\r
381                         }\r
382                 }\r
383 \r
384                 public ICollection ElementMembers\r
385                 {\r
386                         get { return _elementMembers; }\r
387                 }\r
388 \r
389                 public ArrayList AllMembers\r
390                 {\r
391                         get { return _allMembers; }\r
392                 }\r
393 \r
394                 public ArrayList FlatLists\r
395                 {\r
396                         get { return _flatLists; }\r
397                 }\r
398                 \r
399                 public ArrayList MembersWithDefault\r
400                 {\r
401                         get { return _membersWithDefault; }\r
402                 }
403                 
404                 public ArrayList ListMembers\r
405                 {\r
406                         get { return _listMembers; }\r
407                 }
408 \r
409                 public XmlTypeMapMember XmlTextCollector\r
410                 {\r
411                         get { return _xmlTextCollector; }\r
412                 }\r
413                 \r
414                 public XmlTypeMapMember ReturnMember\r
415                 {\r
416                         get { return _returnMember; }\r
417                 }\r
418 \r
419                 public XmlQualifiedName SimpleContentBaseType\r
420                 {\r
421                         get\r
422                         {\r
423                                 if (!_canBeSimpleType || _elementMembers == null || _elementMembers.Count != 1) return null;\r
424                                 XmlTypeMapMemberElement member = (XmlTypeMapMemberElement) _elementMembers[0];\r
425                                 if (member.ElementInfo.Count != 1) return null;\r
426                                 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];\r
427                                 if (!einfo.IsTextElement) return null;\r
428                                 if (member.TypeData.SchemaType == SchemaTypes.Primitive || member.TypeData.SchemaType == SchemaTypes.Enum)\r
429                                         return new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);\r
430                                 return null;\r
431                         }\r
432                 }\r
433                 \r
434                 public void SetCanBeSimpleType (bool can)\r
435                 {\r
436                         _canBeSimpleType = can;\r
437                 }\r
438 \r
439                 public bool HasSimpleContent\r
440                 {\r
441                         get\r
442                         {\r
443                                 return SimpleContentBaseType != null;\r
444                         }\r
445                 }\r
446 \r
447         }\r
448 \r
449         // Mapping info for arrays and lists\r
450 \r
451         internal class ListMap: ObjectMap\r
452         {\r
453                 XmlTypeMapElementInfoList _itemInfo;\r
454                 bool _gotNestedMapping;\r
455                 XmlTypeMapping _nestedArrayMapping;
456                 string _choiceMember;
457 \r
458                 public bool IsMultiArray\r
459                 {\r
460                         get\r
461                         {\r
462                                 return (NestedArrayMapping != null);\r
463                         }\r
464                 }\r
465 \r
466                 public string ChoiceMember
467                 {
468                         get { return _choiceMember; }
469                         set { _choiceMember = value; }
470                 }
471
472                 public XmlTypeMapping NestedArrayMapping\r
473                 {\r
474                         get\r
475                         {\r
476                                 if (_gotNestedMapping) return _nestedArrayMapping;\r
477                                 _gotNestedMapping = true;\r
478 \r
479                                 _nestedArrayMapping = ((XmlTypeMapElementInfo)_itemInfo[0]).MappedType;\r
480 \r
481                                 if (_nestedArrayMapping == null) return null;\r
482                                 \r
483                                 if (_nestedArrayMapping.TypeData.SchemaType != SchemaTypes.Array) {\r
484                                         _nestedArrayMapping = null; return null;\r
485                                 }\r
486 \r
487                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
488                                         if (elem.MappedType != _nestedArrayMapping) {\r
489                                                 _nestedArrayMapping = null;\r
490                                                 return null;\r
491                                         }\r
492 \r
493                                 return _nestedArrayMapping;\r
494                         }\r
495                 }\r
496 \r
497                 public XmlTypeMapElementInfoList ItemInfo\r
498                 {\r
499 \r
500                         get { return _itemInfo; }\r
501                         set { _itemInfo = value; }\r
502                 }\r
503 \r
504                 public XmlTypeMapElementInfo FindElement (object ob, int index, object memberValue)\r
505                 {\r
506                         if (_itemInfo.Count == 1) \r
507                                 return (XmlTypeMapElementInfo) _itemInfo[0];\r
508                         else if (_choiceMember != null && index != -1)
509                         {
510                                 Array values = (Array) XmlTypeMapMember.GetValue (ob, _choiceMember);
511                                 if (values == null || index >= values.Length)
512                                         throw new InvalidOperationException ("Invalid or missing choice enum value in member '" + _choiceMember + "'.");
513                                 object val = values.GetValue (index);
514                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)
515                                         if (elem.ChoiceValue != null && elem.ChoiceValue.Equals (val))
516                                                 return elem;
517                         }
518                         else\r
519                         {\r
520                                 if (memberValue == null) return null;\r
521                                 Type type = memberValue.GetType();\r
522                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
523                                         if (elem.TypeData.Type == type) return elem;\r
524                         }\r
525                         return null;\r
526                 }       \r
527 \r
528                 public XmlTypeMapElementInfo FindElement (string elementName, string ns)\r
529                 {\r
530                         foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
531                                 if (elem.ElementName == elementName && elem.Namespace == ns) return elem;\r
532                         return null;\r
533                 }\r
534                 \r
535                 public XmlTypeMapElementInfo FindTextElement ()\r
536                 {\r
537                         foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
538                                 if (elem.IsTextElement) return elem;\r
539                         return null;\r
540                 }\r
541                 \r
542                 public string GetSchemaArrayName ()\r
543                 {\r
544                         XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) _itemInfo[0];\r
545                         if (einfo.MappedType != null) return TypeTranslator.GetArrayName (einfo.MappedType.XmlType);\r
546                         else return TypeTranslator.GetArrayName (einfo.TypeData.XmlType);\r
547                 }\r
548 \r
549                 public void GetArrayType (int itemCount, out string localName, out string ns)\r
550                 {\r
551                         string arrayDim;\r
552                         if (itemCount != -1) arrayDim = "[" + itemCount + "]";\r
553                         else arrayDim = "[]";\r
554 \r
555                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];\r
556                         if (info.TypeData.SchemaType == SchemaTypes.Array)\r
557                         {\r
558                                 string nm;\r
559                                 ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);\r
560                                 localName = nm + arrayDim;\r
561                         }\r
562                         else \r
563                         {\r
564                                 if (info.MappedType != null)\r
565                                 {\r
566                                         localName = info.MappedType.XmlType + arrayDim;\r
567                                         ns = info.MappedType.Namespace;\r
568                                 }\r
569                                 else \r
570                                 {\r
571                                         localName = info.TypeData.XmlType + arrayDim;\r
572                                         ns = info.DataTypeNamespace;\r
573                                 }\r
574                         }\r
575                 }\r
576 \r
577                 public override bool Equals (object other)\r
578                 {\r
579                         ListMap lmap = other as ListMap;\r
580                         if (lmap == null) return false;\r
581 \r
582                         if (_itemInfo.Count != lmap._itemInfo.Count) return false;\r
583                         for (int n=0; n<_itemInfo.Count; n++)\r
584                                 if (!_itemInfo[n].Equals (lmap._itemInfo[n])) return false;\r
585                         return true;\r
586                 }\r
587 \r
588                 public override int GetHashCode ()\r
589                 {\r
590                         return base.GetHashCode ();\r
591                 }\r
592         }\r
593 \r
594         internal class EnumMap: ObjectMap\r
595         {\r
596                 EnumMapMember[] _members;\r
597                 bool _isFlags;\r
598 \r
599                 public class EnumMapMember\r
600                 {\r
601                         string _xmlName;\r
602                         string _enumName;\r
603                         string _documentation;\r
604 \r
605                         public EnumMapMember (string xmlName, string enumName)\r
606                         {\r
607                                 _xmlName = xmlName;\r
608                                 _enumName = enumName;\r
609                         }\r
610 \r
611                         public string XmlName\r
612                         {\r
613                                 get { return _xmlName; }\r
614                         }\r
615 \r
616                         public string EnumName\r
617                         {\r
618                                 get { return _enumName; }\r
619                         }\r
620 \r
621                         public string Documentation\r
622                         {\r
623                                 get { return _documentation; }\r
624                                 set { _documentation = value; }\r
625                         }\r
626                 }\r
627 \r
628                 public EnumMap (EnumMapMember[] members, bool isFlags)\r
629                 {\r
630                         _members = members;\r
631                         _isFlags = isFlags;\r
632                 }\r
633                 \r
634                 public bool IsFlags\r
635                 {\r
636                         get { return _isFlags; }\r
637                 }\r
638 \r
639                 public EnumMapMember[] Members\r
640                 {\r
641                         get { return _members; }\r
642                 }\r
643 \r
644                 public string GetXmlName (object enumValue)\r
645                 {\r
646                         string enumName = enumValue.ToString();\r
647 \r
648                         if (_isFlags && enumName.IndexOf (',') != -1)\r
649                         {\r
650                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();\r
651                                 string[] enumNames = enumValue.ToString().Split (',');\r
652                                 foreach (string name in enumNames)\r
653                                 {\r
654                                         string tname = name.Trim();\r
655                                         foreach (EnumMapMember mem in _members)\r
656                                                 if (mem.EnumName == tname) {\r
657                                                         sb.Append (mem.XmlName).Append (' ');\r
658                                                         break;\r
659                                                 }\r
660                                 }\r
661                                 sb.Remove (sb.Length-1, 1);\r
662                                 return sb.ToString ();\r
663                         }\r
664 \r
665                         foreach (EnumMapMember mem in _members)\r
666                                 if (mem.EnumName == enumName) return mem.XmlName;\r
667                         \r
668                         // Enum default value will not be written\r
669                         // unless it is one of the enum legal values\r
670                         if (enumName == "0" && IsFlags)\r
671                                 return String.Empty;\r
672                         else\r
673                                 return Convert.ToInt64(enumValue).ToString(CultureInfo.InvariantCulture);\r
674                 }\r
675 \r
676                 public string GetEnumName (string xmlName)\r
677                 {\r
678                         if (_isFlags && xmlName.Length == 0) \r
679                                 return "0";\r
680                         \r
681                         if (_isFlags && xmlName.Trim().IndexOf (' ') != -1)\r
682                         {\r
683                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();\r
684                                 string[] enumNames = xmlName.ToString().Split (' ');\r
685                                 foreach (string name in enumNames)\r
686                                 {\r
687                                         if (name == string.Empty) continue;\r
688                                         string foundEnumValue = null;\r
689                                         foreach (EnumMapMember mem in _members)\r
690                                                 if (mem.XmlName == name) { foundEnumValue = mem.EnumName; break; }\r
691 \r
692                                         if (foundEnumValue != null) sb.Append (foundEnumValue).Append (','); \r
693                                         else return null;\r
694                                 }\r
695                                 sb.Remove (sb.Length-1, 1);\r
696                                 return sb.ToString ();\r
697                         }\r
698 \r
699                         foreach (EnumMapMember mem in _members)\r
700                                 if (mem.XmlName == xmlName) return mem.EnumName;\r
701                                 \r
702                         return null;\r
703                 }\r
704         }\r
705 }\r