merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlTypeMapping.cs
1 //
2 // XmlTypeMapping.cs: 
3 //
4 // Author:
5 //   John Donagher (john@webmeta.com)
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // (C) 2002 John Donagher
9 //
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
32 using System.Xml;
33 using System;
34 using System.Collections;
35 using System.Globalization;
36 using System.Xml.Schema;
37
38 namespace System.Xml.Serialization
39 {
40         public class XmlTypeMapping : XmlMapping
41         {
42                 private string xmlType;
43                 private string xmlTypeNamespace;
44                 TypeData type;
45                 XmlTypeMapping baseMap;
46                 bool multiReferenceType = false;
47                 bool isSimpleType;
48                 string documentation;
49                 bool includeInSchema;
50                 bool isNullable = true;
51
52                 ArrayList _derivedTypes = new ArrayList();
53
54                 internal XmlTypeMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
55                 : base (elementName, ns)
56                 {
57                         this.type = typeData;
58                         this.xmlType = xmlType;
59                         this.xmlTypeNamespace = xmlTypeNamespace;
60                 }
61
62 #if !NET_2_0
63                 public string ElementName
64                 {
65                         get { return _elementName; }
66                 }
67
68                 public string Namespace
69                 {
70                         get { return _namespace; }
71                 }
72 #endif
73
74                 public string TypeFullName
75                 {
76                         get { return type.FullTypeName; }
77                 }
78
79                 public string TypeName
80                 {
81                         get { return type.TypeName; }
82                 }
83
84 #if NET_2_0
85                 public string XsdTypeName
86                 {
87                         get { return XmlType; }
88                 }
89
90                 public string XsdTypeNamespace
91                 {
92                         get { return XmlTypeNamespace; }
93                 }
94 #endif
95
96                 internal TypeData TypeData
97                 {
98                         get { return type; }
99                 }
100
101                 internal string XmlType
102                 {
103                         get { return xmlType; }
104                 }
105
106                 internal string XmlTypeNamespace
107                 {
108                         get { return xmlTypeNamespace; }
109                 }
110
111                 internal ArrayList DerivedTypes
112                 {
113                         get { return _derivedTypes; }
114                         set { _derivedTypes = value; }
115                 }
116
117                 internal bool MultiReferenceType
118                 {
119                         get { return multiReferenceType; }
120                         set { multiReferenceType = value; }
121                 }
122
123                 internal XmlTypeMapping BaseMap
124                 {
125                         get { return baseMap; }
126                         set { baseMap = value; }
127                 }
128
129                 internal bool IsSimpleType
130                 {
131                         get { return isSimpleType; }
132                         set { isSimpleType = value; }
133                 }
134
135                 internal string Documentation
136                 {
137                         set { documentation = value; }
138                         get { return documentation; }
139                 }
140
141                 internal bool IncludeInSchema
142                 {
143                         get { return includeInSchema; }
144                         set { includeInSchema = value; }
145                 }
146                 
147                 internal bool IsNullable
148                 {
149                         get { return isNullable; }
150                         set { isNullable = value; }
151                 }
152
153                 internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)
154                 {
155                         if (TypeData.SchemaType == SchemaTypes.Enum)
156                                 return this;
157
158                         // Returns the map for a subtype of this map's type
159                         objectFullTypeName = objectFullTypeName.Replace ('+','.');
160                         if (TypeFullName == objectFullTypeName) return this;
161                         for (int n=0; n<_derivedTypes.Count; n++) {
162                                 XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];
163                                 if (map.TypeFullName == objectFullTypeName) return map;
164                         }
165                         
166                         return null;
167                 }
168
169                 internal XmlTypeMapping GetRealElementMap (string name, string ens)
170                 {
171                         if (xmlType == name && xmlTypeNamespace == ens) return this;
172                         foreach (XmlTypeMapping map in _derivedTypes)
173                                 if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;
174                         
175                         return null;
176                 }
177                 
178                 internal void UpdateRoot (XmlQualifiedName qname)
179                 {
180                         if (qname != null) {
181                                 this._elementName = qname.Name;
182                                 this._namespace = qname.Namespace;
183                         }
184                 }
185         }
186
187  
188         // Mapping info for XmlSerializable
189         internal class XmlSerializableMapping : XmlTypeMapping
190         {
191                 XmlSchema _schema;
192
193                 internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
194                         : base(elementName, ns, typeData, xmlType, xmlTypeNamespace)
195                 {
196                         IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type);
197                         _schema = serializable.GetSchema();
198                         if (_schema != null) 
199                         {
200                                 if (_schema.Id == null || _schema.Id.Length == 0) 
201                                         throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id.");
202                         }
203                 }
204
205                 internal XmlSchema Schema
206                 {
207                         get { return _schema; }
208                 }
209         }
210  
211
212         // Mapping info for classes and structs
213
214         internal class ClassMap: ObjectMap
215         {
216                 Hashtable _elements = new Hashtable ();
217                 ArrayList _elementMembers;
218                 Hashtable _attributeMembers;
219                 XmlTypeMapMemberAttribute[] _attributeMembersArray;
220                 XmlTypeMapElementInfo[] _elementsByIndex;
221                 ArrayList _flatLists;
222                 ArrayList _allMembers = new ArrayList ();
223                 ArrayList _membersWithDefault;
224                 ArrayList _listMembers;
225                 XmlTypeMapMemberAnyElement _defaultAnyElement;
226                 XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;
227                 XmlTypeMapMemberNamespaces _namespaceDeclarations;
228                 XmlTypeMapMember _xmlTextCollector;
229                 XmlTypeMapMember _returnMember;
230                 bool _ignoreMemberNamespace;
231                 bool _canBeSimpleType = true;
232
233                 public void AddMember (XmlTypeMapMember member)
234                 {
235                         member.GlobalIndex = _allMembers.Count;
236                         _allMembers.Add (member);
237                         
238                         if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {
239                                 if (_membersWithDefault == null) _membersWithDefault = new ArrayList ();
240                                 _membersWithDefault.Add (member);
241                         }
242                         
243                         if (member.IsReturnValue)
244                                 _returnMember = member;
245                         
246                         if (member is XmlTypeMapMemberAttribute)
247                         {
248                                 XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;
249                                 if (_attributeMembers == null) _attributeMembers = new Hashtable();
250                                 string key = BuildKey (atm.AttributeName, atm.Namespace);
251                                 if (_attributeMembers.ContainsKey (key))
252                                         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.");
253                                 member.Index = _attributeMembers.Count;
254                                 _attributeMembers.Add (key, member);
255                                 return;
256                         }
257                         else if (member is XmlTypeMapMemberFlatList)
258                         {
259                                 RegisterFlatList ((XmlTypeMapMemberFlatList)member);
260                         }
261                         else if (member is XmlTypeMapMemberAnyElement)
262                         {
263                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement) member;
264                                 if (mem.IsDefaultAny) _defaultAnyElement = mem;
265                                 if (mem.TypeData.IsListType) RegisterFlatList (mem);
266                         }
267                         else if (member is XmlTypeMapMemberAnyAttribute)
268                         {
269                                 _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute) member;
270                                 return;
271                         }
272                         else if (member is XmlTypeMapMemberNamespaces)
273                         {
274                                 _namespaceDeclarations = (XmlTypeMapMemberNamespaces) member;
275                                 return;
276                         }
277
278                         if (member is XmlTypeMapMemberElement && ((XmlTypeMapMemberElement)member).IsXmlTextCollector)
279                         {
280                                 if (_xmlTextCollector != null) throw new InvalidOperationException ("XmlTextAttribute can only be applied once in a class");
281                                 _xmlTextCollector = member;
282                         }
283
284                         if (_elementMembers == null) {
285                                 _elementMembers = new ArrayList();
286                                 _elements = new Hashtable();
287                         }
288
289                         member.Index = _elementMembers.Count;
290                         _elementMembers.Add (member);
291
292                         ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;
293                         foreach (XmlTypeMapElementInfo elem in elemsInfo)
294                         {
295                                 string key = BuildKey (elem.ElementName, elem.Namespace);
296                                 if (_elements.ContainsKey (key)) 
297                                         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.");
298                                 _elements.Add (key, elem);
299                         }
300                         
301                         if (member.TypeData.IsListType && member.TypeData.Type != null && !member.TypeData.Type.IsArray) {
302                                 if (_listMembers == null) _listMembers = new ArrayList ();
303                                 _listMembers.Add (member);
304                         }
305                 }
306
307                 void RegisterFlatList (XmlTypeMapMemberExpandable member)
308                 {
309                         if (_flatLists == null) _flatLists = new ArrayList ();
310                         member.FlatArrayIndex = _flatLists.Count;
311                         _flatLists.Add (member);
312                 }
313
314                 public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)
315                 {
316                         if (_attributeMembers == null) return null;
317                         return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)];
318                 }
319
320                 public XmlTypeMapElementInfo GetElement (string name, string ns)
321                 {
322                         if (_elements == null) return null;
323                         return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)];
324                 }
325                 
326                 public XmlTypeMapElementInfo GetElement (int index)
327                 {
328                         if (_elements == null) return null;
329                         
330                         if (_elementsByIndex == null)
331                         {
332                                 _elementsByIndex = new XmlTypeMapElementInfo [_elementMembers.Count];
333                                 foreach (XmlTypeMapMemberElement mem in _elementMembers)
334                                 {
335                                         if (mem.ElementInfo.Count != 1) 
336                                                 throw new InvalidOperationException ("Read by order only possible for encoded/bare format");
337                                                 
338                                         _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];
339                                 }
340                         }
341                         
342                         return _elementsByIndex [index];
343                 }
344                 
345                 private string BuildKey (string name, string ns)
346                 {
347                         if (_ignoreMemberNamespace) return name;
348                         else return name + " / " + ns;
349                 }
350                 
351                 public ICollection AllElementInfos
352                 {
353                         get { return _elements.Values; }
354                 }
355                 
356                 
357                 public bool IgnoreMemberNamespace
358                 {
359                         get { return _ignoreMemberNamespace; }
360                         set { _ignoreMemberNamespace = value; }
361                 }
362
363                 public XmlTypeMapMember FindMember (string name)
364                 {
365                         for (int n=0; n<_allMembers.Count; n++)
366                                 if (((XmlTypeMapMember)_allMembers[n]).Name == name) return (XmlTypeMapMember)_allMembers[n];
367                         return null;
368                 }
369
370                 public XmlTypeMapMemberAnyElement DefaultAnyElementMember
371                 {
372                         get { return _defaultAnyElement; }
373                 }
374
375                 public XmlTypeMapMemberAnyAttribute DefaultAnyAttributeMember
376                 {
377                         get { return _defaultAnyAttribute; }
378                 }
379
380                 public XmlTypeMapMemberNamespaces NamespaceDeclarations
381                 {
382                         get { return _namespaceDeclarations; }
383                 }
384
385                 public ICollection AttributeMembers
386                 {
387                         get 
388                         {
389                                 if (_attributeMembers == null) return null;
390                                 if (_attributeMembersArray != null) return _attributeMembersArray;
391                                 
392                                 _attributeMembersArray = new XmlTypeMapMemberAttribute[_attributeMembers.Count];
393                                 foreach (XmlTypeMapMemberAttribute mem in _attributeMembers.Values)
394                                         _attributeMembersArray [mem.Index] = mem;
395                                 return _attributeMembersArray;
396                         }
397                 }
398
399                 public ICollection ElementMembers
400                 {
401                         get { return _elementMembers; }
402                 }
403
404                 public ArrayList AllMembers
405                 {
406                         get { return _allMembers; }
407                 }
408
409                 public ArrayList FlatLists
410                 {
411                         get { return _flatLists; }
412                 }
413                 
414                 public ArrayList MembersWithDefault
415                 {
416                         get { return _membersWithDefault; }
417                 }
418                 
419                 public ArrayList ListMembers
420                 {
421                         get { return _listMembers; }
422                 }
423
424                 public XmlTypeMapMember XmlTextCollector
425                 {
426                         get { return _xmlTextCollector; }
427                 }
428                 
429                 public XmlTypeMapMember ReturnMember
430                 {
431                         get { return _returnMember; }
432                 }
433
434                 public XmlQualifiedName SimpleContentBaseType
435                 {
436                         get
437                         {
438                                 if (!_canBeSimpleType || _elementMembers == null || _elementMembers.Count != 1) return null;
439                                 XmlTypeMapMemberElement member = (XmlTypeMapMemberElement) _elementMembers[0];
440                                 if (member.ElementInfo.Count != 1) return null;
441                                 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];
442                                 if (!einfo.IsTextElement) return null;
443                                 if (member.TypeData.SchemaType == SchemaTypes.Primitive || member.TypeData.SchemaType == SchemaTypes.Enum)
444                                         return new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
445                                 return null;
446                         }
447                 }
448                 
449                 public void SetCanBeSimpleType (bool can)
450                 {
451                         _canBeSimpleType = can;
452                 }
453
454                 public bool HasSimpleContent
455                 {
456                         get
457                         {
458                                 return SimpleContentBaseType != null;
459                         }
460                 }
461
462         }
463
464         // Mapping info for arrays and lists
465
466         internal class ListMap: ObjectMap
467         {
468                 XmlTypeMapElementInfoList _itemInfo;
469                 bool _gotNestedMapping;
470                 XmlTypeMapping _nestedArrayMapping;
471                 string _choiceMember;
472
473                 public bool IsMultiArray
474                 {
475                         get
476                         {
477                                 return (NestedArrayMapping != null);
478                         }
479                 }
480
481                 public string ChoiceMember
482                 {
483                         get { return _choiceMember; }
484                         set { _choiceMember = value; }
485                 }
486
487                 public XmlTypeMapping NestedArrayMapping
488                 {
489                         get
490                         {
491                                 if (_gotNestedMapping) return _nestedArrayMapping;
492                                 _gotNestedMapping = true;
493
494                                 _nestedArrayMapping = ((XmlTypeMapElementInfo)_itemInfo[0]).MappedType;
495
496                                 if (_nestedArrayMapping == null) return null;
497                                 
498                                 if (_nestedArrayMapping.TypeData.SchemaType != SchemaTypes.Array) {
499                                         _nestedArrayMapping = null; return null;
500                                 }
501
502                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)
503                                         if (elem.MappedType != _nestedArrayMapping) {
504                                                 _nestedArrayMapping = null;
505                                                 return null;
506                                         }
507
508                                 return _nestedArrayMapping;
509                         }
510                 }
511
512                 public XmlTypeMapElementInfoList ItemInfo
513                 {
514
515                         get { return _itemInfo; }
516                         set { _itemInfo = value; }
517                 }
518
519                 public XmlTypeMapElementInfo FindElement (object ob, int index, object memberValue)
520                 {
521                         if (_itemInfo.Count == 1) 
522                                 return (XmlTypeMapElementInfo) _itemInfo[0];
523                         else if (_choiceMember != null && index != -1)
524                         {
525                                 Array values = (Array) XmlTypeMapMember.GetValue (ob, _choiceMember);
526                                 if (values == null || index >= values.Length)
527                                         throw new InvalidOperationException ("Invalid or missing choice enum value in member '" + _choiceMember + "'.");
528                                 object val = values.GetValue (index);
529                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)
530                                         if (elem.ChoiceValue != null && elem.ChoiceValue.Equals (val))
531                                                 return elem;
532                         }
533                         else
534                         {
535                                 if (memberValue == null) return null;
536                                 Type type = memberValue.GetType();
537                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)
538                                         if (elem.TypeData.Type == type) return elem;
539                         }
540                         return null;
541                 }       
542
543                 public XmlTypeMapElementInfo FindElement (string elementName, string ns)
544                 {
545                         foreach (XmlTypeMapElementInfo elem in _itemInfo)
546                                 if (elem.ElementName == elementName && elem.Namespace == ns) return elem;
547                         return null;
548                 }
549                 
550                 public XmlTypeMapElementInfo FindTextElement ()
551                 {
552                         foreach (XmlTypeMapElementInfo elem in _itemInfo)
553                                 if (elem.IsTextElement) return elem;
554                         return null;
555                 }
556                 
557                 public string GetSchemaArrayName ()
558                 {
559                         XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) _itemInfo[0];
560                         if (einfo.MappedType != null) return TypeTranslator.GetArrayName (einfo.MappedType.XmlType);
561                         else return TypeTranslator.GetArrayName (einfo.TypeData.XmlType);
562                 }
563
564                 public void GetArrayType (int itemCount, out string localName, out string ns)
565                 {
566                         string arrayDim;
567                         if (itemCount != -1) arrayDim = "[" + itemCount + "]";
568                         else arrayDim = "[]";
569
570                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];
571                         if (info.TypeData.SchemaType == SchemaTypes.Array)
572                         {
573                                 string nm;
574                                 ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);
575                                 localName = nm + arrayDim;
576                         }
577                         else 
578                         {
579                                 if (info.MappedType != null)
580                                 {
581                                         localName = info.MappedType.XmlType + arrayDim;
582                                         ns = info.MappedType.Namespace;
583                                 }
584                                 else 
585                                 {
586                                         localName = info.TypeData.XmlType + arrayDim;
587                                         ns = info.DataTypeNamespace;
588                                 }
589                         }
590                 }
591
592                 public override bool Equals (object other)
593                 {
594                         ListMap lmap = other as ListMap;
595                         if (lmap == null) return false;
596
597                         if (_itemInfo.Count != lmap._itemInfo.Count) return false;
598                         for (int n=0; n<_itemInfo.Count; n++)
599                                 if (!_itemInfo[n].Equals (lmap._itemInfo[n])) return false;
600                         return true;
601                 }
602
603                 public override int GetHashCode ()
604                 {
605                         return base.GetHashCode ();
606                 }
607         }
608
609         internal class EnumMap: ObjectMap
610         {
611                 readonly EnumMapMember[] _members;
612                 readonly bool _isFlags;
613                 readonly string[] _enumNames = null;
614                 readonly string[] _xmlNames = null;
615                 readonly long[] _values = null;
616
617                 public class EnumMapMember
618                 {
619                         readonly string _xmlName;
620                         readonly string _enumName;
621                         readonly long _value;
622                         string _documentation;
623
624                         public EnumMapMember (string xmlName, string enumName)
625                                 : this (xmlName, enumName, 0)
626                         {
627                         }
628
629                         public EnumMapMember (string xmlName, string enumName, long value)
630                         {
631                                 _xmlName = xmlName;
632                                 _enumName = enumName;
633                                 _value = value;
634                         }
635
636                         public string XmlName
637                         {
638                                 get { return _xmlName; }
639                         }
640
641                         public string EnumName
642                         {
643                                 get { return _enumName; }
644                         }
645
646                         public long Value
647                         {
648                                 get { return _value; }
649                         }
650
651                         public string Documentation
652                         {
653                                 get { return _documentation; }
654                                 set { _documentation = value; }
655                         }
656                 }
657
658                 public EnumMap (EnumMapMember[] members, bool isFlags)
659                 {
660                         _members = members;
661                         _isFlags = isFlags;
662
663                         _enumNames = new string[_members.Length];
664                         _xmlNames = new string[_members.Length];
665                         _values = new long[_members.Length];
666
667                         for (int i = 0; i < _members.Length; i++) {
668                                 EnumMapMember mem = _members[i];
669                                 _enumNames[i] = mem.EnumName;
670                                 _xmlNames[i] = mem.XmlName;
671                                 _values[i] = mem.Value;
672                         }
673                 }
674                 
675                 public bool IsFlags
676                 {
677                         get { return _isFlags; }
678                 }
679
680                 public EnumMapMember[] Members
681                 {
682                         get { return _members; }
683                 }
684
685                 public string[] EnumNames
686                 {
687                         get {
688                                 return _enumNames;
689                         }
690                 }
691
692                 public string[] XmlNames
693                 {
694                         get {
695                                 return _xmlNames;
696                         }
697                 }
698
699                 public long[] Values
700                 {
701                         get {
702                                 return _values;
703                         }
704                 }
705
706                 public string GetXmlName (string typeName, object enumValue)
707                 {
708                         if (enumValue is string) {
709                                 throw new InvalidCastException ();
710                         }
711
712                         long value = 0;
713
714                         try {
715                                 value = ((IConvertible) enumValue).ToInt64 (CultureInfo.CurrentCulture);
716                         } catch (FormatException) {
717                                 throw new InvalidCastException ();
718                         }
719
720                         for (int i = 0; i < Values.Length; i++) {
721                                 if (Values[i] == value)
722                                         return XmlNames[i];
723                         }
724
725                         if (IsFlags && value == 0)
726                                 return string.Empty;
727
728                         string xmlName = string.Empty;
729                         if (IsFlags) {
730 #if NET_2_0
731                                 xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values, typeName);
732 #else
733                                 xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values);
734 #endif
735                         }
736
737                         if (xmlName.Length == 0) {
738 #if NET_2_0
739                                 throw new InvalidOperationException (string.Format(CultureInfo.CurrentCulture,
740                                         "'{0}' is not a valid value for {1}.", value, typeName));
741 #else
742                                 return value.ToString (CultureInfo.InvariantCulture);
743 #endif
744                         }
745                         return xmlName;
746                 }
747
748                 public string GetEnumName (string typeName, string xmlName)
749                 {
750                         if (_isFlags) {
751                                 xmlName = xmlName.Trim ();
752                                 if (xmlName.Length == 0)
753                                         return "0";
754
755                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
756                                 string[] enumNames = xmlName.Split (null);
757                                 foreach (string name in enumNames) {
758                                         if (name == string.Empty) continue;
759                                         string foundEnumValue = null;
760                                         for (int i = 0; i < XmlNames.Length; i++)
761                                                 if (XmlNames[i] == name) {
762                                                         foundEnumValue = EnumNames[i];
763                                                         break;
764                                                 }
765
766                                         if (foundEnumValue != null) {
767                                                 if (sb.Length > 0)
768                                                         sb.Append (',');
769                                                 sb.Append (foundEnumValue);
770                                         } else {
771                                                 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
772                                                         "'{0}' is not a valid value for {1}.", name, typeName));
773                                         }
774                                 }
775                                 return sb.ToString ();
776                         }
777
778                         foreach (EnumMapMember mem in _members)
779                                 if (mem.XmlName == xmlName) return mem.EnumName;
780                                 
781                         return null;
782                 }
783         }
784 }