2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.XML / System.Xml.Serialization / XmlSchemaImporter.cs
blob91e8fac3481be9412f4fb729c8aead31dedbe809
1 //
2 // System.Xml.Serialization.XmlSchemaImporter
3 //
4 // Author:
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
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.
32 using System.Xml;
33 #if !TARGET_JVM && !MONOTOUCH
34 using System.CodeDom.Compiler;
35 #endif
36 using System.Xml.Schema;
37 using System.Collections;
38 #if NET_2_0 && CONFIGURATION_DEP
39 using System.Configuration;
40 using System.Xml.Serialization.Configuration;
41 #endif
43 namespace System.Xml.Serialization
45 public class XmlSchemaImporter
46 #if NET_2_0 && !MONOTOUCH
47 : SchemaImporter
48 #endif
50 #region Fields
52 XmlSchemas schemas;
53 CodeIdentifiers typeIdentifiers;
54 CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
55 Hashtable mappedTypes = new Hashtable ();
56 Hashtable primitiveDerivedMappedTypes = new Hashtable ();
57 Hashtable dataMappedTypes = new Hashtable ();
58 Queue pendingMaps = new Queue ();
59 Hashtable sharedAnonymousTypes = new Hashtable ();
60 bool encodedFormat = false;
61 XmlReflectionImporter auxXmlRefImporter;
62 SoapReflectionImporter auxSoapRefImporter;
63 bool anyTypeImported;
65 #if NET_2_0
66 CodeGenerationOptions options;
67 #endif
69 static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
70 static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
71 static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
73 const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
75 XmlSchemaElement anyElement = null;
77 class MapFixup
79 public XmlTypeMapping Map;
80 public XmlSchemaComplexType SchemaType;
81 public XmlQualifiedName TypeName;
84 #endregion
86 #region Constructors
88 public XmlSchemaImporter (XmlSchemas schemas)
90 this.schemas = schemas;
91 typeIdentifiers = new CodeIdentifiers ();
93 InitializeExtensions ();
96 public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
97 : this (schemas)
99 this.typeIdentifiers = typeIdentifiers;
102 #if NET_2_0
103 #if !TARGET_JVM && !MONOTOUCH
104 [MonoTODO]
105 public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)
107 this.schemas = schemas;
108 this.options = options;
109 if (context != null) {
110 typeIdentifiers = context.TypeIdentifiers;
111 InitSharedData (context);
113 else
114 typeIdentifiers = new CodeIdentifiers ();
116 InitializeExtensions ();
118 #endif
120 public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)
122 this.schemas = schemas;
123 this.options = options;
124 if (context != null) {
125 typeIdentifiers = context.TypeIdentifiers;
126 InitSharedData (context);
128 else
129 typeIdentifiers = new CodeIdentifiers ();
131 InitializeExtensions ();
135 public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)
137 this.typeIdentifiers = typeIdentifiers;
138 this.schemas = schemas;
139 this.options = options;
141 InitializeExtensions ();
144 void InitSharedData (ImportContext context)
146 if (context.ShareTypes) {
147 mappedTypes = context.MappedTypes;
148 dataMappedTypes = context.DataMappedTypes;
149 sharedAnonymousTypes = context.SharedAnonymousTypes;
152 #endif
154 internal bool UseEncodedFormat
156 get { return encodedFormat; }
157 set { encodedFormat = value; }
160 #endregion // Constructors
162 #region Methods
164 void InitializeExtensions ()
166 #if NET_2_0 && CONFIGURATION_DEP
167 SerializationSectionGroup root = ConfigurationManager.GetSection ("system.xml.serialization") as SerializationSectionGroup;
168 if (root == null)
169 return;
171 foreach (SchemaImporterExtensionElement element in
172 root.SchemaImporterExtensions.SchemaImporterExtensions)
173 Extensions.Add (element.Name, element.Type);
174 #endif
177 public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
179 if (typeName == XmlQualifiedName.Empty)
181 XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
182 mapMem.Name = typeName.Name;
183 mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
184 mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None));
186 XmlMemberMapping[] mm = new XmlMemberMapping [1];
187 mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
188 return new XmlMembersMapping (mm);
190 else
192 XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));
193 if (stype == null)
194 throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");
196 if (!CanBeAnyElement (stype))
197 throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");
199 ClassMap cmap = new ClassMap ();
200 CodeIdentifiers classIds = new CodeIdentifiers ();
201 bool isMixed = stype.IsMixed;
202 ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);
203 XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];
204 mapMem.Name = typeName.Name;
206 XmlMemberMapping[] mm = new XmlMemberMapping [1];
207 mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
208 return new XmlMembersMapping (mm);
212 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
214 return ImportDerivedTypeMapping (name, baseType, true);
217 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
219 XmlQualifiedName qname;
220 XmlSchemaType stype;
222 if (encodedFormat)
224 qname = name;
225 stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
226 if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
228 else
230 if (!LocateElement (name, out qname, out stype))
231 return null;
234 XmlTypeMapping map = GetRegisteredTypeMapping (qname, baseType);
235 if (map != null)
237 // If the type has already been imported, make sure that the map
238 // has the requested base type
240 SetMapBaseType (map, baseType);
241 map.UpdateRoot (name);
242 return map;
245 map = CreateTypeMapping (qname, SchemaTypes.Class, name);
246 if (stype != null) {
247 map.Documentation = GetDocumentation (stype);
248 RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
249 } else {
250 ClassMap cmap = new ClassMap ();
251 CodeIdentifiers classIds = new CodeIdentifiers ();
252 map.ObjectMap = cmap;
253 AddTextMember (qname, cmap, classIds);
256 BuildPendingMaps ();
257 SetMapBaseType (map, baseType);
259 return map;
262 void SetMapBaseType (XmlTypeMapping map, Type baseType)
264 // This method sets the base type for a given map.
265 // If the map already inherits from this type, it does nothing.
267 // Fiirst of all, check if the map already inherits from baseType
269 XmlTypeMapping topMap = null;
270 while (map != null)
272 if (map.TypeData.Type == baseType)
273 return;
274 topMap = map;
275 map = map.BaseMap;
278 // Does not have the requested base type.
279 // Then, get/create a map for that base type.
281 XmlTypeMapping baseMap = ReflectType (baseType);
283 // Add this map as a derived map of the base map
285 topMap.BaseMap = baseMap;
286 baseMap.DerivedTypes.Add (topMap);
287 baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);
289 // Now add the base type fields to all derived maps
291 ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
293 ClassMap cmap = (ClassMap)topMap.ObjectMap;
294 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
295 cmap.AddMember (member);
297 foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)
299 cmap = (ClassMap)derivedMap.ObjectMap;
300 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
301 cmap.AddMember (member);
305 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
307 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
308 if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
310 XmlSchemaComplexType stype;
311 if (elem.SchemaType != null)
313 stype = elem.SchemaType as XmlSchemaComplexType;
315 else
317 if (elem.SchemaTypeName.IsEmpty) return null;
318 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
319 if (type == null) {
320 if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;
321 throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
323 stype = type as XmlSchemaComplexType;
326 if (stype == null)
327 throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
329 XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);
330 return new XmlMembersMapping (name.Name, name.Namespace, mapping);
333 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
335 XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
336 for (int n=0; n<names.Length; n++)
338 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
339 if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
341 XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
342 XmlTypeMapping tmap;
343 TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);
345 mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap);
347 BuildPendingMaps ();
348 return new XmlMembersMapping (mapping);
351 #if NET_2_0
352 [MonoTODO]
353 public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)
355 throw new NotImplementedException ();
358 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)
360 return ImportSchemaType (typeName, typeof (object));
363 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)
365 return ImportSchemaType (typeName, typeof (object), false);
368 [MonoTODO ("baseType and baseTypeCanBeIndirect are ignored")]
369 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)
371 XmlSchemaType stype =
372 (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaComplexType)) ??
373 (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaSimpleType));
374 return ImportTypeCommon (typeName, typeName, stype, true);
376 #endif
378 internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
380 XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
381 for (int n=0; n<members.Length; n++)
383 TypeData td = GetTypeData (members[n].MemberType, null, false); // FIXME: isNullable could be true?
384 XmlTypeMapping tmap = GetTypeMapping (td);
385 mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap);
387 BuildPendingMaps ();
388 return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
391 internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
393 XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
394 if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
396 XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);
397 return new XmlMembersMapping (name, ns, mapping);
400 XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
402 if (stype.Particle == null)
403 return new XmlMemberMapping [0];
405 ClassMap cmap = new ClassMap ();
407 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
408 if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
410 CodeIdentifiers classIds = new CodeIdentifiers ();
411 ImportParticleComplexContent (refer, cmap, seq, classIds, false);
412 ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);
414 BuildPendingMaps ();
416 int n = 0;
417 XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
418 foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
419 mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
421 return mapping;
424 XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap)
426 XmlTypeMapMemberElement mapMem;
428 if (type.IsListType)
429 mapMem = new XmlTypeMapMemberList ();
430 else
431 mapMem = new XmlTypeMapMemberElement ();
433 mapMem.Name = name;
434 mapMem.TypeData = type;
435 mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap));
436 return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
439 [MonoTODO]
440 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
442 throw new NotImplementedException ();
445 public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
447 XmlQualifiedName qname;
448 XmlSchemaType stype;
450 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
451 if (!LocateElement (elem, out qname, out stype))
452 throw new InvalidOperationException (String.Format ("'{0}' is missing.", name));
453 return ImportTypeCommon (name, qname, stype, elem.IsNillable);
456 // FIXME: name and qname are confusing. Rename one either
457 // (name is in schema itself, qname is for actual processing.
458 // For example simple types have qname as in xsd namespace.)
459 private XmlTypeMapping ImportTypeCommon (XmlQualifiedName name, XmlQualifiedName qname, XmlSchemaType stype, bool isNullable)
461 if (stype == null) {
462 if (qname == anyType) {
463 // Importing anyType.
464 XmlTypeMapping xmap = GetTypeMapping (TypeTranslator.GetTypeData (typeof (object)));
465 // This also means, all complexTypes
466 // are imported as well.
467 BuildPendingMaps ();
468 return xmap;
469 } else {
470 // Importing a primitive type
471 TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);
472 return ReflectType (td, name.Namespace);
476 XmlTypeMapping map = GetRegisteredTypeMapping (qname);
477 if (map != null) return map;
479 if (stype is XmlSchemaSimpleType)
480 return ImportClassSimpleType (stype.QualifiedName, (XmlSchemaSimpleType) stype, name);
482 map = CreateTypeMapping (qname, SchemaTypes.Class, name);
483 map.Documentation = GetDocumentation (stype);
484 map.IsNullable = isNullable;
485 RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
487 BuildPendingMaps ();
488 return map;
491 bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
493 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
494 return LocateElement (elem, out qname, out stype);
497 bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)
499 qname = null;
500 stype = null;
502 if (elem == null) return false;
504 // The root element must be an element with complex type
506 if (elem.SchemaType != null)
508 stype = elem.SchemaType;
509 qname = elem.QualifiedName;
511 else if (elem.ElementType == XmlSchemaComplexType.AnyType)
513 qname = anyType;
514 return true;
516 else
518 if (elem.SchemaTypeName.IsEmpty) return false;
520 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
521 if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
522 if (type == null) {
523 if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {
524 qname = elem.SchemaTypeName;
525 return true;
527 throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
529 stype = (XmlSchemaType) type;
530 qname = stype.QualifiedName;
532 XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;
533 if (btype != null && btype.QualifiedName == elem.SchemaTypeName)
534 throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");
537 //if (stype is XmlSchemaSimpleType) return false;
538 return true;
541 XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)
543 XmlTypeMapping map = GetRegisteredTypeMapping (name);
544 if (map != null) {
545 map.UpdateRoot (root);
546 return map;
549 XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
550 if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
552 if (type == null)
554 if (throwOnError) {
555 if (name.Namespace == XmlSerializer.EncodingNamespace)
556 throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");
557 else
558 throw new InvalidOperationException ("Referenced type '" + name + "' not found.");
559 } else
560 return null;
563 return ImportType (name, type, root);
566 XmlTypeMapping ImportClass (XmlQualifiedName name)
568 XmlTypeMapping map = ImportType (name, null, true);
569 if (map.TypeData.SchemaType == SchemaTypes.Class) return map;
570 XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
571 return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));
574 XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
576 XmlTypeMapping map = GetRegisteredTypeMapping (name);
577 if (map != null) {
578 XmlSchemaComplexType ct = stype as XmlSchemaComplexType;
579 if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {
580 map.UpdateRoot (root);
581 return map;
584 // The map was initially imported as a class, but it turns out that it is an
585 // array. It has to be imported now as array.
588 if (stype is XmlSchemaComplexType)
589 return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
590 else if (stype is XmlSchemaSimpleType)
591 return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
593 throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
596 XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
598 // The need for fixups: If the complex type is an array, then to get the type of the
599 // array we need first to get the type of the items of the array.
600 // But if one of the item types or its children has a referece to this type array,
601 // then we enter in an infinite loop. This does not happen with class types because
602 // the class map is registered before parsing the children. We can't do the same
603 // with the array type because to register the array map we need the type of the array.
605 Type anyType = GetAnyElementType (stype);
606 if (anyType != null)
607 return GetTypeMapping (TypeTranslator.GetTypeData(anyType));
609 if (CanBeArray (typeQName, stype))
611 TypeData typeData;
612 ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
613 if (listMap != null)
615 XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);
616 map.ObjectMap = listMap;
617 return map;
620 // After all, it is not an array. Create a class map then.
622 else if (CanBeIXmlSerializable (stype))
624 return ImportXmlSerializableMapping (typeQName.Namespace);
627 // Register the map right now but do not build it,
628 // This will avoid loops.
630 return CreateClassMap (typeQName, stype, root);
633 XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
635 XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
636 map.Documentation = GetDocumentation (stype);
637 RegisterMapFixup (map, typeQName, stype);
638 return map;
641 void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
643 MapFixup fixup = new MapFixup ();
644 fixup.Map = map;
645 fixup.SchemaType = stype;
646 fixup.TypeName = typeQName;
647 pendingMaps.Enqueue (fixup);
650 void BuildPendingMaps ()
652 while (pendingMaps.Count > 0) {
653 MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();
654 if (fixup.Map.ObjectMap == null) {
655 BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
656 if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
661 void BuildPendingMap (XmlTypeMapping map)
663 if (map.ObjectMap != null) return;
665 foreach (MapFixup fixup in pendingMaps)
667 if (fixup.Map == map) {
668 BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
669 return;
672 throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
675 void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
677 CodeIdentifiers classIds = new CodeIdentifiers();
678 classIds.AddReserved (map.TypeData.TypeName);
680 ClassMap cmap = new ClassMap ();
681 map.ObjectMap = cmap;
682 bool isMixed = stype.IsMixed;
684 if (stype.Particle != null)
685 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
686 else
688 if (stype.ContentModel is XmlSchemaSimpleContent) {
689 ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
691 else if (stype.ContentModel is XmlSchemaComplexContent) {
692 ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
696 ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
697 ImportExtensionTypes (typeQName);
699 if (isMixed) AddTextMember (typeQName, cmap, classIds);
701 AddObjectDerivedMap (map);
704 void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
706 atts = CollectAttributeUsesNonOverlap (atts, cmap);
708 if (anyat != null)
710 XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
711 member.Name = classIds.AddUnique ("AnyAttribute", member);
712 member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
713 cmap.AddMember (member);
716 foreach (XmlSchemaObject at in atts)
718 if (at is XmlSchemaAttribute)
720 string ns;
721 XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
722 XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
723 XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
724 member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
725 member.Documentation = GetDocumentation (attr);
726 member.AttributeName = refAttr.Name;
727 member.Namespace = ns;
728 member.Form = refAttr.Form;
729 member.TypeData = GetAttributeTypeData (typeQName, attr);
731 if (refAttr.DefaultValue != null)
732 member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);
733 else if (member.TypeData.IsValueType)
734 member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);
736 if (member.TypeData.IsComplexType)
737 member.MappedType = GetTypeMapping (member.TypeData);
738 cmap.AddMember (member);
740 else if (at is XmlSchemaAttributeGroupRef)
742 XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
743 XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
744 ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
749 // Attributes might be redefined, so there is an existing attribute for the same name, skip it.
750 // FIXME: this is nothing more than just a hack.
751 // Basically it should use
752 // XmlSchemaComplexType.AttributeUses.
753 XmlSchemaObjectCollection CollectAttributeUsesNonOverlap (
754 XmlSchemaObjectCollection src, ClassMap map)
756 XmlSchemaObjectCollection atts = new XmlSchemaObjectCollection ();
757 foreach (XmlSchemaAttribute a in src)
758 if (map.GetAttribute (a.QualifiedName.Name, a.QualifiedName.Namespace) == null)
759 atts.Add (a);
760 return atts;
763 ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
765 if (encodedFormat)
767 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
768 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
769 XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
771 if (arrayTypeAt != null)
773 XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
774 if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
776 XmlAttribute xat = null;
777 foreach (XmlAttribute at in uatts)
778 if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
779 { xat = at; break; }
781 if (xat == null)
782 throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
784 string name, ns, dims;
785 TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
786 return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
788 else
790 XmlSchemaElement elem = null;
791 XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
792 if (seq != null && seq.Items.Count == 1)
793 elem = seq.Items[0] as XmlSchemaElement;
794 else {
795 XmlSchemaAll all = rest.Particle as XmlSchemaAll;
796 if (all != null && all.Items.Count == 1)
797 elem = all.Items[0] as XmlSchemaElement;
799 if (elem == null)
800 throw new InvalidOperationException ("Unknown array format");
802 return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
805 else
807 ClassMap cmap = new ClassMap ();
808 CodeIdentifiers classIds = new CodeIdentifiers();
809 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);
811 XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
812 if (list != null && list.ChoiceMember == null)
814 arrayTypeData = list.TypeData;
815 return list.ListMap;
817 else
819 arrayTypeData = null;
820 return null;
825 ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
827 ListMap map = new ListMap ();
829 int i = type.LastIndexOf ("[");
830 if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
831 if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
833 string itemType = type.Substring (0,i);
835 TypeData itemTypeData;
836 if (itemType.IndexOf ("[") != -1)
838 ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
840 int dims = itemType.Split ('[').Length - 1;
841 string name = TypeTranslator.GetArrayName (type, dims);
842 XmlQualifiedName qname = new XmlQualifiedName (name, ns);
843 XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
844 tmap.ObjectMap = innerListMap;
846 else
848 itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null, false);
851 arrayTypeData = itemTypeData.ListTypeData;
853 map.ItemInfo = new XmlTypeMapElementInfoList();
854 map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None));
855 return map;
858 XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
860 foreach (object ob in atts)
862 XmlSchemaAttribute att = ob as XmlSchemaAttribute;
863 if (att != null && att.RefName == arrayTypeRefName) return att;
865 XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
866 if (gref != null)
868 XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
869 att = FindArrayAttribute (grp.Attributes);
870 if (att != null) return att;
873 return null;
876 void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
878 ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
879 if (isMixed) AddTextMember (typeQName, cmap, classIds);
882 void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)
884 if (cmap.XmlTextCollector == null)
886 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
887 member.Name = classIds.AddUnique ("Text", member);
888 member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
889 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
890 member.IsXmlTextCollector = true;
891 member.ListMap = new ListMap ();
892 member.ListMap.ItemInfo = member.ElementInfo;
893 cmap.AddMember (member);
897 void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
899 if (particle == null) return;
901 if (particle is XmlSchemaGroupRef)
902 particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
904 if (particle.MaxOccurs > 1) multiValue = true;
906 if (particle is XmlSchemaSequence) {
907 ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
909 else if (particle is XmlSchemaChoice) {
910 if (((XmlSchemaChoice)particle).Items.Count == 1)
911 ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
912 else
913 ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
915 else if (particle is XmlSchemaAll) {
916 ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
920 void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
922 foreach (XmlSchemaObject item in items)
924 if (item is XmlSchemaElement)
926 string ns;
927 XmlSchemaElement elem = (XmlSchemaElement) item;
928 XmlTypeMapping emap;
929 TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
930 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
932 if (elem.MaxOccurs == 1 && !multiValue)
934 XmlTypeMapMemberElement member = null;
935 if (typeData.SchemaType != SchemaTypes.Array)
937 member = new XmlTypeMapMemberElement ();
938 if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);
940 else if (GetTypeMapping (typeData).IsSimpleType)
942 // It is a simple list (space separated list).
943 // Since this is not supported, map as a single item value
944 member = new XmlTypeMapMemberElement ();
945 #if NET_2_0
946 // In MS.NET those types are mapped to a string
947 typeData = TypeTranslator.GetTypeData(typeof(string));
948 #else
949 typeData = typeData.ListItemTypeData;
950 #endif
952 else
953 member = new XmlTypeMapMemberList ();
955 if (elem.MinOccurs == 0 && typeData.IsValueType)
956 member.IsOptionalValueType = true;
958 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
959 member.Documentation = GetDocumentation (elem);
960 member.TypeData = typeData;
961 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
962 cmap.AddMember (member);
964 else
966 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
967 member.ListMap = new ListMap ();
968 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
969 member.Documentation = GetDocumentation (elem);
970 member.TypeData = typeData.ListTypeData;
971 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
972 member.ListMap.ItemInfo = member.ElementInfo;
973 cmap.AddMember (member);
976 else if (item is XmlSchemaAny)
978 XmlSchemaAny elem = (XmlSchemaAny) item;
979 XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
980 member.Name = classIds.AddUnique ("Any", member);
981 member.Documentation = GetDocumentation (elem);
983 Type ctype;
984 if (elem.MaxOccurs != 1 || multiValue)
985 ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
986 else
987 ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
989 member.TypeData = TypeTranslator.GetTypeData (ctype);
990 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
991 einfo.IsUnnamedAnyElement = true;
992 member.ElementInfo.Add (einfo);
994 if (isMixed)
996 einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
997 member.ElementInfo.Add (einfo);
998 member.IsXmlTextCollector = true;
999 isMixed = false; //Allow only one XmlTextAttribute
1002 cmap.AddMember (member);
1004 else if (item is XmlSchemaParticle) {
1005 ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
1010 object ImportDefaultValue (TypeData typeData, string value)
1012 if (typeData.SchemaType == SchemaTypes.Enum) {
1013 XmlTypeMapping map = GetTypeMapping (typeData);
1014 EnumMap emap = (EnumMap) map.ObjectMap;
1015 string res = emap.GetEnumName (map.TypeFullName, value);
1016 if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
1017 return res;
1018 } else
1019 return XmlCustomFormatter.FromXmlString (typeData, value);
1022 void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
1024 XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
1025 multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
1026 if (choices.Count == 0) return;
1028 if (choice.MaxOccurs > 1) multiValue = true;
1030 XmlTypeMapMemberElement member;
1031 if (multiValue)
1033 member = new XmlTypeMapMemberFlatList ();
1034 member.Name = classIds.AddUnique ("Items", member);
1035 ListMap listMap = new ListMap ();
1036 listMap.ItemInfo = choices;
1037 ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
1039 else
1041 member = new XmlTypeMapMemberElement ();
1042 member.Name = classIds.AddUnique ("Item", member);
1045 // If all choices have the same type, use that type for the member.
1046 // If not use System.Object.
1047 // If there are at least two choices with the same type, use a choice
1048 // identifier attribute
1050 TypeData typeData = null;
1051 bool twoEqual = false;
1052 bool allEqual = true;
1053 Hashtable types = new Hashtable ();
1055 for (int n = choices.Count - 1; n >= 0; n--)
1057 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];
1059 // In some complex schemas, we may end up with several options
1060 // with the same name. It is better to ignore the extra options
1061 // than to crash. It's the best we can do, and btw it works
1062 // better than in MS.NET.
1064 if (cmap.GetElement (einfo.ElementName, einfo.Namespace) != null ||
1065 choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)
1067 choices.RemoveAt (n);
1068 continue;
1071 if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
1072 else types.Add (einfo.TypeData, einfo);
1074 TypeData choiceType = einfo.TypeData;
1075 if (choiceType.SchemaType == SchemaTypes.Class)
1077 // When comparing class types, use the most generic class in the
1078 // inheritance hierarchy
1080 XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
1081 BuildPendingMap (choiceMap);
1082 while (choiceMap.BaseMap != null) {
1083 choiceMap = choiceMap.BaseMap;
1084 BuildPendingMap (choiceMap);
1085 choiceType = choiceMap.TypeData;
1089 if (typeData == null) typeData = choiceType;
1090 else if (typeData != choiceType) allEqual = false;
1093 if (!allEqual)
1094 typeData = TypeTranslator.GetTypeData (typeof(object));
1096 if (twoEqual)
1098 // Create the choice member
1099 XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
1100 choiceMember.Ignore = true;
1101 choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
1102 member.ChoiceMember = choiceMember.Name;
1104 // Create the choice enum
1105 XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
1106 enumMap.IncludeInSchema = false;
1108 CodeIdentifiers codeIdents = new CodeIdentifiers ();
1109 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
1110 for (int n=0; n<choices.Count; n++)
1112 XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
1113 bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);
1114 string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;
1115 string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
1116 members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
1118 enumMap.ObjectMap = new EnumMap (members, false);
1120 choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
1121 choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None));
1122 cmap.AddMember (choiceMember);
1125 if (typeData == null)
1126 return;
1128 if (multiValue)
1129 typeData = typeData.ListTypeData;
1131 member.ElementInfo = choices;
1132 member.Documentation = GetDocumentation (choice);
1133 member.TypeData = typeData;
1134 cmap.AddMember (member);
1137 bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
1139 bool multiValue = false;
1140 foreach (XmlSchemaObject titem in items)
1142 XmlSchemaObject item = titem;
1143 if (item is XmlSchemaGroupRef)
1144 item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
1146 if (item is XmlSchemaElement)
1148 string ns;
1149 XmlSchemaElement elem = (XmlSchemaElement) item;
1150 XmlTypeMapping emap;
1151 TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
1152 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
1153 choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
1154 if (elem.MaxOccurs > 1) multiValue = true;
1156 else if (item is XmlSchemaAny)
1158 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
1159 einfo.IsUnnamedAnyElement = true;
1160 choices.Add (einfo);
1162 else if (item is XmlSchemaChoice) {
1163 multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
1165 else if (item is XmlSchemaSequence) {
1166 multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
1169 return multiValue;
1172 void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
1174 XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
1175 ClassMap cmap = (ClassMap)map.ObjectMap;
1176 XmlQualifiedName qname = GetContentBaseType (content.Content);
1177 TypeData simpleType = null;
1179 if (!IsPrimitiveTypeNamespace (qname.Namespace))
1181 // Add base map members to this map
1183 XmlTypeMapping baseMap = ImportType (qname, null, true);
1184 BuildPendingMap (baseMap);
1186 if (baseMap.IsSimpleType) {
1187 simpleType = baseMap.TypeData;
1188 } else {
1189 ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
1191 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
1192 cmap.AddMember (member);
1194 map.BaseMap = baseMap;
1195 baseMap.DerivedTypes.Add (map);
1198 else
1199 simpleType = FindBuiltInType (qname);
1201 if (simpleType != null) {
1202 XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
1203 member.Name = classIds.AddUnique("Value", member);
1204 member.TypeData = simpleType;
1205 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
1206 member.IsXmlTextCollector = true;
1207 cmap.AddMember (member);
1210 if (ext != null)
1211 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
1214 TypeData FindBuiltInType (XmlQualifiedName qname)
1216 XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
1217 if (ct != null)
1219 XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
1220 if (sc == null) throw new InvalidOperationException ("Invalid schema");
1221 return FindBuiltInType (GetContentBaseType (sc.Content));
1224 XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
1225 if (st != null)
1226 return FindBuiltInType (qname, st);
1228 if (IsPrimitiveTypeNamespace (qname.Namespace))
1229 return TypeTranslator.GetPrimitiveTypeData (qname.Name);
1231 throw new InvalidOperationException ("Definition of type '" + qname + "' not found");
1234 TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
1236 if (CanBeEnum (st) && qname != null)
1237 return ImportType (qname, null, true).TypeData;
1239 if (st.Content is XmlSchemaSimpleTypeRestriction) {
1240 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;
1241 XmlQualifiedName bn = GetContentBaseType (rest);
1242 if (bn == XmlQualifiedName.Empty && rest.BaseType != null)
1243 return FindBuiltInType (qname, rest.BaseType);
1244 else
1245 return FindBuiltInType (bn);
1247 else if (st.Content is XmlSchemaSimpleTypeList) {
1248 return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
1250 else if (st.Content is XmlSchemaSimpleTypeUnion) {
1251 // MS.NET always import simple unions as string
1252 return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema.Namespace));
1254 else
1255 return null;
1258 XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
1260 if (ob is XmlSchemaSimpleContentExtension)
1261 return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
1262 else if (ob is XmlSchemaSimpleContentRestriction)
1263 return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
1264 else if (ob is XmlSchemaSimpleTypeRestriction)
1265 return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
1266 else if (ob is XmlSchemaSimpleTypeList)
1267 return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
1268 else
1269 return null;
1272 void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
1274 ClassMap cmap = (ClassMap)map.ObjectMap;
1275 XmlQualifiedName qname;
1277 XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
1278 if (ext != null) qname = ext.BaseTypeName;
1279 else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
1281 if (qname == typeQName)
1282 throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");
1284 // Add base map members to this map
1286 XmlTypeMapping baseMap = ImportClass (qname);
1287 BuildPendingMap (baseMap);
1288 ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
1290 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
1291 cmap.AddMember (member);
1293 if (baseClassMap.XmlTextCollector != null) isMixed = false;
1294 else if (content.IsMixed) isMixed = true;
1296 map.BaseMap = baseMap;
1297 baseMap.DerivedTypes.Add (map);
1299 if (ext != null) {
1300 // Add the members of this map
1301 ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
1302 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
1304 else {
1305 if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
1309 void ImportExtensionTypes (XmlQualifiedName qname)
1311 foreach (XmlSchema schema in schemas) {
1312 foreach (XmlSchemaObject sob in schema.Items)
1314 XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
1315 if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
1316 XmlQualifiedName exqname;
1317 XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
1318 if (ext != null) exqname = ext.BaseTypeName;
1319 else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
1320 if (exqname == qname)
1321 ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
1327 XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
1329 if (CanBeEnum (stype))
1331 // Create an enum map
1333 CodeIdentifiers codeIdents = new CodeIdentifiers ();
1334 XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, root);
1335 enumMap.Documentation = GetDocumentation (stype);
1337 bool isFlags = false;
1338 if (stype.Content is XmlSchemaSimpleTypeList) {
1339 stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
1340 isFlags = true;
1342 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
1344 codeIdents.AddReserved (enumMap.TypeData.TypeName);
1346 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
1347 for (int n=0; n<rest.Facets.Count; n++)
1349 XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
1350 string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
1351 members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
1352 members [n].Documentation = GetDocumentation (enu);
1354 enumMap.ObjectMap = new EnumMap (members, isFlags);
1355 enumMap.IsSimpleType = true;
1356 return enumMap;
1359 if (stype.Content is XmlSchemaSimpleTypeList)
1361 XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
1362 TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
1364 ListMap listMap = new ListMap ();
1366 listMap.ItemInfo = new XmlTypeMapElementInfoList ();
1367 listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None));
1369 XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
1370 map.ObjectMap = listMap;
1371 map.IsSimpleType = true;
1372 return map;
1375 // It is an extension of a primitive or known type
1377 TypeData typeData = FindBuiltInType (typeQName, stype);
1378 XmlTypeMapping rmap = GetTypeMapping (typeData);
1380 // The resulting map must be a simple type. It needs to be explicitely set for arrays
1381 rmap.IsSimpleType = true;
1382 return rmap;
1385 bool CanBeEnum (XmlSchemaSimpleType stype)
1387 if (stype.Content is XmlSchemaSimpleTypeRestriction)
1389 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
1390 if (rest.Facets.Count == 0) return false;
1391 foreach (object ob in rest.Facets)
1392 if (!(ob is XmlSchemaEnumerationFacet)) return false;
1393 return true;
1395 else if (stype.Content is XmlSchemaSimpleTypeList)
1397 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;
1398 return (list.ItemType != null && CanBeEnum (list.ItemType));
1400 return false;
1403 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)
1405 if (encodedFormat)
1407 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
1408 if (content == null) return false;
1409 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
1410 if (rest == null) return false;
1411 return rest.BaseTypeName == arrayType;
1413 else
1415 if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;
1416 else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);
1420 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)
1422 // To be an array, there can't be a direct child of type typeQName
1424 if (particle == null) return false;
1426 multiValue = multiValue || particle.MaxOccurs > 1;
1428 if (particle is XmlSchemaGroupRef)
1429 return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);
1431 if (particle is XmlSchemaElement)
1433 XmlSchemaElement elem = (XmlSchemaElement)particle;
1434 if (!elem.RefName.IsEmpty)
1435 return CanBeArray (typeQName, FindRefElement (elem), multiValue);
1436 else
1437 return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);
1440 if (particle is XmlSchemaAny)
1441 return multiValue;
1443 if (particle is XmlSchemaSequence)
1445 XmlSchemaSequence seq = particle as XmlSchemaSequence;
1446 if (seq.Items.Count != 1) return false;
1447 return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);
1450 if (particle is XmlSchemaChoice)
1452 // Can be array if all choices have different types
1453 ArrayList types = new ArrayList ();
1454 if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;
1455 return multiValue;
1458 return false;
1461 bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)
1463 XmlQualifiedName type = null;
1465 multiValue = multiValue || particle.MaxOccurs > 1;
1467 if (particle is XmlSchemaGroupRef)
1468 return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);
1470 if (particle is XmlSchemaElement) {
1471 string ns;
1472 XmlSchemaElement elem = (XmlSchemaElement)particle;
1473 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
1474 if (refElem.SchemaType != null) return true;
1475 type = refElem.SchemaTypeName;
1477 else if (particle is XmlSchemaAny) {
1478 type = anyType;
1480 else if (particle is XmlSchemaSequence)
1482 XmlSchemaSequence seq = particle as XmlSchemaSequence;
1483 foreach (XmlSchemaParticle par in seq.Items)
1484 if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;
1485 return true;
1487 else if (particle is XmlSchemaChoice)
1489 foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)
1490 if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;
1491 return true;
1494 if (typeQName.Equals (type)) return false;
1496 // For primitive types, compare using CLR types, since several
1497 // xml types can be mapped to a single CLR type
1499 string t;
1500 if (IsPrimitiveTypeNamespace (type.Namespace))
1501 t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;
1503 else
1504 t = type.Name + ":" + type.Namespace;
1506 if (types.Contains (t)) return false;
1507 types.Add (t);
1508 return true;
1511 bool CanBeAnyElement (XmlSchemaComplexType stype)
1513 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1514 return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);
1517 Type GetAnyElementType (XmlSchemaComplexType stype)
1519 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1521 if ((seq == null) || (seq.Items.Count != 1) || !(seq.Items[0] is XmlSchemaAny))
1522 return null;
1524 if (encodedFormat)
1525 return typeof(object);
1527 XmlSchemaAny any = seq.Items[0] as XmlSchemaAny;
1528 if (any.MaxOccurs == 1)
1530 if (stype.IsMixed)
1531 return typeof(XmlNode);
1532 else
1533 return typeof(XmlElement);
1535 else
1537 if (stype.IsMixed)
1538 return typeof(XmlNode[]);
1539 else
1540 return typeof(XmlElement[]);
1544 bool CanBeIXmlSerializable (XmlSchemaComplexType stype)
1546 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1547 if (seq == null) return false;
1548 if (seq.Items.Count != 2) return false;
1549 XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;
1550 if (elem == null) return false;
1551 if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;
1552 return (seq.Items[1] is XmlSchemaAny);
1555 XmlTypeMapping ImportXmlSerializableMapping (string ns)
1557 XmlQualifiedName qname = new XmlQualifiedName ("System.Data.DataSet",ns);
1558 XmlTypeMapping map = GetRegisteredTypeMapping (qname);
1559 if (map != null) return map;
1561 TypeData typeData = new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes.XmlSerializable, null);
1562 map = new XmlTypeMapping ("System.Data.DataSet", "", typeData, "System.Data.DataSet", ns);
1563 map.IncludeInSchema = true;
1564 RegisterTypeMapping (qname, typeData, map);
1565 return map;
1568 XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form)
1570 if (typeData.IsComplexType)
1571 return CreateElementInfo (ns, member, name, typeData, isNillable, form, GetTypeMapping (typeData));
1572 else
1573 return CreateElementInfo (ns, member, name, typeData, isNillable, form, null);
1576 XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, XmlTypeMapping emap)
1578 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
1579 einfo.ElementName = name;
1580 einfo.Namespace = ns;
1581 einfo.IsNullable = isNillable;
1582 einfo.Form = form;
1583 if (typeData.IsComplexType)
1584 einfo.MappedType = emap;
1585 return einfo;
1588 XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)
1590 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
1591 einfo.IsTextElement = true;
1592 einfo.WrappedElement = false;
1593 if (typeData.IsComplexType)
1594 einfo.MappedType = GetTypeMapping (typeData);
1595 return einfo;
1598 XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)
1600 string typeName = CodeIdentifier.MakeValid (typeQName.Name);
1601 typeName = typeIdentifiers.AddUnique (typeName, null);
1603 TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);
1605 string rootElem;
1606 string rootNs;
1607 if (root != null) {
1608 rootElem = root.Name;
1609 rootNs = root.Namespace;
1611 else {
1612 rootElem = typeQName.Name;
1613 rootNs = "";
1616 XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);
1617 map.IncludeInSchema = true;
1618 RegisterTypeMapping (typeQName, typeData, map);
1620 return map;
1623 XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)
1625 XmlTypeMapping map;
1626 if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);
1627 else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);
1629 map.IncludeInSchema = true;
1630 RegisterTypeMapping (typeQName, arrayTypeData, map);
1632 return map;
1635 XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)
1638 if (!elem.RefName.IsEmpty)
1640 ns = elem.RefName.Namespace;
1641 return FindRefElement (elem);
1643 else
1645 ns = typeQName.Namespace;
1646 return elem;
1650 XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)
1652 if (!attr.RefName.IsEmpty)
1654 ns = attr.RefName.Namespace;
1655 XmlSchemaAttribute at = FindRefAttribute (attr.RefName);
1656 if (at == null) throw new InvalidOperationException ("The attribute " + attr.RefName + " is missing");
1657 return at;
1659 else
1661 ns = attr.ParentIsSchema ? typeQName.Namespace : String.Empty;
1662 return attr;
1666 TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem, XmlQualifiedName root, out XmlTypeMapping map)
1668 bool sharedAnnType = false;
1669 map = null;
1671 if (!elem.RefName.IsEmpty) {
1672 XmlSchemaElement refElem = FindRefElement (elem);
1673 if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);
1674 root = elem.RefName;
1675 elem = refElem;
1676 sharedAnnType = true;
1679 TypeData td;
1680 if (!elem.SchemaTypeName.IsEmpty) {
1681 td = GetTypeData (elem.SchemaTypeName, root, elem.IsNillable);
1682 map = GetRegisteredTypeMapping (td);
1684 else if (elem.SchemaType == null)
1685 td = TypeTranslator.GetTypeData (typeof(object));
1686 else
1687 td = GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);
1689 if (map == null && td.IsComplexType)
1690 map = GetTypeMapping (td);
1692 return td;
1695 TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)
1697 bool sharedAnnType = false;
1699 if (!attr.RefName.IsEmpty) {
1700 XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);
1701 if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);
1702 attr = refAtt;
1703 sharedAnnType = true;
1706 if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null, false);
1707 if (attr.SchemaType == null) return TypeTranslator.GetTypeData (typeof(string));
1708 else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);
1711 TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root, bool isNullable)
1713 if (IsPrimitiveTypeNamespace (typeQName.Namespace)) {
1714 XmlTypeMapping map = ImportType (typeQName, root, false);
1715 if (map != null) return map.TypeData;
1716 else return TypeTranslator.GetPrimitiveTypeData (typeQName.Name, isNullable);
1719 if (encodedFormat && typeQName.Namespace == "")
1720 return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
1722 return ImportType (typeQName, root, true).TypeData;
1725 TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)
1727 string baseName;
1729 if (sharedAnnType)
1731 // Anonymous types defined in root elements or attributes can be shared among all elements that
1732 // reference this root element or attribute
1733 TypeData std = sharedAnonymousTypes [stype] as TypeData;
1734 if (std != null) return std;
1735 baseName = propertyName;
1737 else
1738 baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);
1740 baseName = elemIdentifiers.AddUnique (baseName, stype);
1742 XmlQualifiedName newName;
1743 newName = new XmlQualifiedName (baseName, typeQNname.Namespace);
1745 XmlTypeMapping map = ImportType (newName, stype, root);
1746 if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;
1748 return map.TypeData;
1751 XmlTypeMapping GetTypeMapping (TypeData typeData)
1753 if (typeData.Type == typeof(object) && !anyTypeImported)
1754 ImportAllObjectTypes ();
1756 XmlTypeMapping map = GetRegisteredTypeMapping (typeData);
1757 if (map != null) return map;
1759 if (typeData.IsListType)
1761 // Create an array map for the type
1763 XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);
1765 map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);
1766 map.IncludeInSchema = true;
1768 ListMap listMap = new ListMap ();
1769 listMap.ItemInfo = new XmlTypeMapElementInfoList();
1770 listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false, XmlSchemaForm.None));
1771 map.ObjectMap = listMap;
1773 RegisterTypeMapping (new XmlQualifiedName(map.ElementName, map.Namespace), typeData, map);
1774 return map;
1776 else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))
1778 return CreateSystemMap (typeData);
1781 throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");
1784 void AddObjectDerivedMap (XmlTypeMapping map)
1786 TypeData typeData = TypeTranslator.GetTypeData (typeof(object));
1787 XmlTypeMapping omap = GetRegisteredTypeMapping (typeData);
1788 if (omap == null)
1789 omap = CreateSystemMap (typeData);
1790 omap.DerivedTypes.Add (map);
1793 XmlTypeMapping CreateSystemMap (TypeData typeData)
1795 XmlTypeMapping map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);
1796 map.IncludeInSchema = false;
1797 map.ObjectMap = new ClassMap ();
1798 dataMappedTypes [typeData] = map;
1799 return map;
1802 void ImportAllObjectTypes ()
1804 // All complex types are subtypes of anyType, so all of them
1805 // must also be imported
1807 anyTypeImported = true;
1808 foreach (XmlSchema schema in schemas) {
1809 foreach (XmlSchemaObject sob in schema.Items)
1811 XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
1812 if (sct != null)
1813 ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
1818 XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName, Type baseType)
1820 // Primitive types with a forced base class are stored in a different table.
1821 // In this way it is possible to have two maps for primitive types: one with
1822 // the forced base class (returned by ImportDerivedTypeMapping) and one
1823 // with the regular primitive map.
1825 if (IsPrimitiveTypeNamespace (typeQName.Namespace))
1826 return (XmlTypeMapping) primitiveDerivedMappedTypes [typeQName];
1827 else
1828 return (XmlTypeMapping) mappedTypes [typeQName];
1831 XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)
1833 return (XmlTypeMapping) mappedTypes [typeQName];
1836 XmlTypeMapping GetRegisteredTypeMapping (TypeData typeData)
1838 return (XmlTypeMapping) dataMappedTypes [typeData];
1841 void RegisterTypeMapping (XmlQualifiedName qname, TypeData typeData, XmlTypeMapping map)
1843 // Primitive types with a forced base class are stored in a different table.
1844 // In this way it is possible to have two maps for primitive types: one with
1845 // the forced base class (returned by ImportDerivedTypeMapping) and one
1846 // with the regular primitive map.
1848 dataMappedTypes [typeData] = map;
1849 if (IsPrimitiveTypeNamespace (qname.Namespace) && !map.IsSimpleType)
1850 primitiveDerivedMappedTypes [qname] = map;
1851 else
1852 mappedTypes [qname] = map;
1855 XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)
1857 XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));
1858 return grp.Particle;
1861 XmlSchemaElement FindRefElement (XmlSchemaElement elem)
1863 XmlSchemaElement refelem = (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));
1864 if (refelem != null) return refelem;
1866 if (IsPrimitiveTypeNamespace (elem.RefName.Namespace))
1868 if (anyElement != null) return anyElement;
1869 anyElement = new XmlSchemaElement ();
1870 anyElement.Name = "any";
1871 anyElement.SchemaTypeName = anyType;
1872 return anyElement;
1873 } else
1874 return null;
1877 XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)
1879 if (refName.Namespace == XmlNamespace)
1881 XmlSchemaAttribute at = new XmlSchemaAttribute ();
1882 at.Name = refName.Name;
1883 at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
1884 return at;
1886 return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));
1889 XmlSchemaAttributeGroup FindRefAttributeGroup (XmlQualifiedName refName)
1891 XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (refName, typeof(XmlSchemaAttributeGroup));
1892 foreach (XmlSchemaObject at in grp.Attributes)
1894 if (at is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)at).RefName == refName)
1895 throw new InvalidOperationException ("Cannot import attribute group '" + refName.Name + "' from namespace '" + refName.Namespace + "'. Redefine not supported");
1898 return grp;
1901 XmlTypeMapping ReflectType (Type type)
1903 TypeData typeData = TypeTranslator.GetTypeData (type);
1904 return ReflectType (typeData, (string) null);
1907 XmlTypeMapping ReflectType (TypeData typeData, string ns)
1909 if (!encodedFormat)
1911 if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();
1912 return auxXmlRefImporter.ImportTypeMapping (typeData, ns);
1914 else
1916 if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();
1917 return auxSoapRefImporter.ImportTypeMapping (typeData, ns);
1922 string GetDocumentation (XmlSchemaAnnotated elem)
1924 string res = "";
1925 XmlSchemaAnnotation anot = elem.Annotation;
1926 if (anot == null || anot.Items == null) return null;
1928 foreach (object ob in anot.Items)
1930 XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;
1931 if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {
1932 if (res != string.Empty) res += "\n";
1933 foreach (XmlNode node in doc.Markup)
1934 res += node.Value;
1937 return res;
1940 bool IsPrimitiveTypeNamespace (string ns)
1942 return (ns == XmlSchema.Namespace) || (encodedFormat && ns == XmlSerializer.EncodingNamespace);
1945 #endregion // Methods