* SoapReflectionImporter.cs: implemented.
[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 \r
11 using System.Xml;\r
12 using System;\r
13 using System.Collections;\r
14 \r
15 namespace System.Xml.Serialization\r
16 {\r
17         public class XmlTypeMapping : XmlMapping\r
18         {\r
19                 private string elementName;\r
20                 private string ns;\r
21                 private string xmlType;\r
22                 TypeData type;\r
23                 bool multiReferenceType = false;\r
24 \r
25                 ArrayList _derivedTypes = new ArrayList();\r
26 \r
27                 internal XmlTypeMapping(string elementName, string ns, TypeData typeData, string xmlType)\r
28                 {\r
29                         this.elementName = elementName;\r
30                         this.ns = ns;\r
31                         this.type = typeData;\r
32                         this.xmlType = xmlType;\r
33                 }\r
34 \r
35                 public string ElementName\r
36                 {\r
37                         get { return elementName; }\r
38                 }\r
39 \r
40                 public string Namespace\r
41                 {\r
42                         get { return ns; }\r
43                 }\r
44 \r
45                 public string TypeFullName\r
46                 {\r
47                         get { return type.FullTypeName; }\r
48                 }\r
49 \r
50                 public string TypeName\r
51                 {\r
52                         get { return type.TypeName; }\r
53                 }\r
54 \r
55                 internal TypeData TypeData\r
56                 {\r
57                         get { return type; }\r
58                 }\r
59 \r
60                 internal string XmlType\r
61                 {\r
62                         get { return xmlType; }\r
63                 }\r
64 \r
65                 internal ArrayList DerivedTypes\r
66                 {\r
67                         get { return _derivedTypes; }\r
68                         set { _derivedTypes = value; }\r
69                 }\r
70 \r
71                 internal bool MultiReferenceType\r
72                 {\r
73                         get { return multiReferenceType; }\r
74                         set { multiReferenceType = value; }\r
75                 }\r
76 \r
77                 internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
78                 {\r
79                         // Returns the map for a subtype of this map's type\r
80 \r
81                         if (TypeFullName == objectFullTypeName) return this;\r
82                         foreach (XmlTypeMapping map in _derivedTypes)\r
83                                 if (map.TypeFullName == objectFullTypeName) return map;\r
84 \r
85                         return null;\r
86                 }\r
87 \r
88                 internal XmlTypeMapping GetRealElementMap (string name, string ens)\r
89                 {\r
90                         if (xmlType == name && ns == ens) return this;\r
91                         foreach (XmlTypeMapping map in _derivedTypes)\r
92                                 if (map.xmlType == name && map.ns == ens) return map;\r
93                         return null;\r
94                 }\r
95         }\r
96 \r
97         // Mapping info for classes and structs\r
98 \r
99         internal class ClassMap: ObjectMap\r
100         {\r
101                 Hashtable _elements;\r
102                 ArrayList _elementMembers;\r
103                 Hashtable _attributeMembers;\r
104                 ArrayList _flatLists;\r
105                 XmlTypeMapMemberAnyElement _defaultAnyElement;\r
106                 XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;\r
107 \r
108                 public void AddMember (XmlTypeMapMember member)\r
109                 {\r
110                         if (member is XmlTypeMapMemberAttribute)\r
111                         {\r
112                                 XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;\r
113                                 if (_attributeMembers == null) _attributeMembers = new Hashtable();\r
114                                 _attributeMembers.Add (atm.AttributeName + "/" + atm.Namespace, member);\r
115                                 return;\r
116                         }\r
117                         else if (member is XmlTypeMapMemberFlatList)\r
118                         {\r
119                                 RegisterFlatList ((XmlTypeMapMemberFlatList)member);\r
120                         }\r
121                         else if (member is XmlTypeMapMemberAnyElement)\r
122                         {\r
123                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement) member;\r
124                                 if (mem.IsDefaultAny) _defaultAnyElement = mem;\r
125                                 if (mem.TypeData.IsListType) RegisterFlatList (mem);\r
126                         }\r
127                         else if (member is XmlTypeMapMemberAnyAttribute)\r
128                         {\r
129                                 _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute) member;\r
130                                 return;\r
131                         }\r
132 \r
133                         if (_elementMembers == null) {\r
134                                 _elementMembers = new ArrayList();\r
135                                 _elements = new Hashtable();\r
136                         }\r
137 \r
138                         member.Index = _elementMembers.Count;\r
139                         _elementMembers.Add (member);\r
140 \r
141                         ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;\r
142                         foreach (XmlTypeMapElementInfo elem in elemsInfo)\r
143                         {\r
144                                 string key = elem.ElementName+"/"+elem.Namespace;\r
145                                 if (_elements.ContainsKey (key)) \r
146                                         throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");\r
147                                 _elements.Add (key, elem);\r
148                         }\r
149                 }\r
150 \r
151                 void RegisterFlatList (XmlTypeMapMemberExpandable member)\r
152                 {\r
153                         if (_flatLists == null) _flatLists = new ArrayList ();\r
154                         member.FlatArrayIndex = _flatLists.Count;\r
155                         _flatLists.Add (member);\r
156                 }\r
157 \r
158                 public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)\r
159                 {\r
160                         if (_attributeMembers == null) return null;\r
161                         return (XmlTypeMapMemberAttribute)_attributeMembers[name + "/" + ns];\r
162                 }\r
163 \r
164                 public XmlTypeMapElementInfo GetElement (string name, string ns)\r
165                 {\r
166                         if (_elements == null) return null;\r
167                         return (XmlTypeMapElementInfo)_elements[name + "/" + ns];\r
168                 }\r
169 \r
170                 public XmlTypeMapMemberAnyElement DefaultAnyElementMember\r
171                 {\r
172                         get { return _defaultAnyElement; }\r
173                 }\r
174 \r
175                 public XmlTypeMapMemberAnyAttribute DefaultAnyAttributeMember\r
176                 {\r
177                         get { return _defaultAnyAttribute; }\r
178                 }\r
179 \r
180                 public ICollection AttributeMembers\r
181                 {\r
182                         get { return (_attributeMembers != null) ? _attributeMembers.Values : null; }\r
183                 }\r
184 \r
185                 public ICollection ElementMembers\r
186                 {\r
187                         get { return _elementMembers; }\r
188                 }\r
189 \r
190                 public ICollection FlatLists\r
191                 {\r
192                         get { return _flatLists; }\r
193                 }\r
194         }\r
195 \r
196         // Mapping info for arrays and lists\r
197 \r
198         internal class ListMap: ObjectMap\r
199         {\r
200                 XmlTypeMapElementInfoList _itemInfo;\r
201 \r
202                 public XmlTypeMapElementInfoList ItemInfo\r
203                 {\r
204                         get { return _itemInfo; }\r
205                         set { _itemInfo = value; }\r
206                 }\r
207 \r
208                 public XmlTypeMapElementInfo FindElement (object memberValue)\r
209                 {\r
210                         if (_itemInfo.Count == 1) \r
211                                 return (XmlTypeMapElementInfo) _itemInfo[0];\r
212                         else\r
213                         {\r
214                                 if (memberValue == null) return null;\r
215                                 Type type = memberValue.GetType();\r
216                                 foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
217                                         if (elem.TypeData.Type == type) return elem;\r
218                         }\r
219                         return null;\r
220                 }       \r
221 \r
222                 public XmlTypeMapElementInfo FindElement (string elementName, string ns)\r
223                 {\r
224                         foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
225                                 if (elem.ElementName == elementName && elem.Namespace == ns) return elem;\r
226                         return null;\r
227                 }\r
228 \r
229                 public void GetArrayType (int itemCount, out string localName, out string ns)\r
230                 {\r
231                         string arrayDim;\r
232                         if (itemCount != -1) arrayDim = "[" + itemCount + "]";\r
233                         else arrayDim = "[]";\r
234 \r
235                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];\r
236                         if (info.TypeData.SchemaType == SchemaTypes.Array)\r
237                         {\r
238                                 string nm;\r
239                                 ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);\r
240                                 localName = nm + arrayDim;\r
241                         }\r
242                         else \r
243                         {\r
244                                 if (info.MappedType != null)\r
245                                 {\r
246                                         localName = info.MappedType.XmlType + arrayDim;\r
247                                         ns = info.MappedType.Namespace;\r
248                                 }\r
249                                 else \r
250                                 {\r
251                                         localName = info.DataType + arrayDim;\r
252                                         ns = info.DataTypeNamespace;\r
253                                 }\r
254                         }\r
255                 }\r
256 \r
257                 public override bool Equals (object other)\r
258                 {\r
259                         ListMap lmap = other as ListMap;\r
260                         if (lmap == null) return false;\r
261 \r
262                         if (_itemInfo.Count != lmap._itemInfo.Count) return false;\r
263                         for (int n=0; n<_itemInfo.Count; n++)\r
264                                 if (!_itemInfo[n].Equals (lmap._itemInfo[n])) return false;\r
265                         return true;\r
266                 }\r
267 \r
268                 public override int GetHashCode ()\r
269                 {\r
270                         return base.GetHashCode ();\r
271                 }\r
272         }\r
273 \r
274         internal class EnumMap: ObjectMap\r
275         {\r
276                 EnumMapMember[] _members;\r
277 \r
278                 public class EnumMapMember\r
279                 {\r
280                         string _xmlName;\r
281                         string _enumName;\r
282 \r
283                         public EnumMapMember (string xmlName, string enumName)\r
284                         {\r
285                                 _xmlName = xmlName;\r
286                                 _enumName = enumName;\r
287                         }\r
288 \r
289                         public string XmlName\r
290                         {\r
291                                 get { return _xmlName; }\r
292                         }\r
293 \r
294                         public string EnumName\r
295                         {\r
296                                 get { return _enumName; }\r
297                         }\r
298                 }\r
299 \r
300                 public EnumMap (EnumMapMember[] members)\r
301                 {\r
302                         _members = members;\r
303                 }\r
304 \r
305                 public EnumMapMember[] Members\r
306                 {\r
307                         get { return _members; }\r
308                 }\r
309 \r
310                 public string GetXmlName (string enumName)\r
311                 {\r
312                         foreach (EnumMapMember mem in _members)\r
313                                 if (mem.EnumName == enumName) return mem.XmlName;\r
314                         throw new InvalidOperationException ("Invalid enumeration value: " + enumName);\r
315                 }\r
316 \r
317                 public string GetEnumName (string xmlName)\r
318                 {\r
319                         foreach (EnumMapMember mem in _members)\r
320                                 if (mem.XmlName == xmlName) return mem.EnumName;\r
321                         throw new InvalidOperationException ("Invalid enumeration value: " + xmlName);\r
322                 }\r
323         }\r
324 }\r