PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System.XML/System.Xml.Serialization/XmlSchemaImporter.cs

https://bitbucket.org/danipen/mono
C# | 1965 lines | 1552 code | 304 blank | 109 comment | 482 complexity | 86c182ba08f4e9a2790ec657b48d12dc MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. using System.Xml;
  31. #if !TARGET_JVM && !MOBILE
  32. using System.CodeDom.Compiler;
  33. #endif
  34. using System.Xml.Schema;
  35. using System.Collections;
  36. #if NET_2_0 && CONFIGURATION_DEP
  37. using System.Configuration;
  38. using System.Xml.Serialization.Configuration;
  39. #endif
  40. namespace System.Xml.Serialization
  41. {
  42. public class XmlSchemaImporter
  43. #if NET_2_0 && !MOBILE
  44. : SchemaImporter
  45. #endif
  46. {
  47. #region Fields
  48. XmlSchemas schemas;
  49. CodeIdentifiers typeIdentifiers;
  50. CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
  51. Hashtable mappedTypes = new Hashtable ();
  52. Hashtable primitiveDerivedMappedTypes = new Hashtable ();
  53. Hashtable dataMappedTypes = new Hashtable ();
  54. Queue pendingMaps = new Queue ();
  55. Hashtable sharedAnonymousTypes = new Hashtable ();
  56. bool encodedFormat = false;
  57. XmlReflectionImporter auxXmlRefImporter;
  58. SoapReflectionImporter auxSoapRefImporter;
  59. bool anyTypeImported;
  60. // CodeGenerationOptions options;
  61. static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
  62. static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
  63. static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
  64. const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
  65. XmlSchemaElement anyElement = null;
  66. class MapFixup
  67. {
  68. public XmlTypeMapping Map;
  69. public XmlSchemaComplexType SchemaType;
  70. public XmlQualifiedName TypeName;
  71. }
  72. #endregion
  73. #region Constructors
  74. public XmlSchemaImporter (XmlSchemas schemas)
  75. {
  76. this.schemas = schemas;
  77. typeIdentifiers = new CodeIdentifiers ();
  78. InitializeExtensions ();
  79. }
  80. public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
  81. : this (schemas)
  82. {
  83. this.typeIdentifiers = typeIdentifiers;
  84. }
  85. #if !TARGET_JVM && !MOBILE
  86. [MonoTODO]
  87. public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)
  88. {
  89. this.schemas = schemas;
  90. // this.options = options;
  91. if (context != null) {
  92. typeIdentifiers = context.TypeIdentifiers;
  93. InitSharedData (context);
  94. }
  95. else
  96. typeIdentifiers = new CodeIdentifiers ();
  97. InitializeExtensions ();
  98. }
  99. [MonoTODO]
  100. public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)
  101. {
  102. this.schemas = schemas;
  103. // this.options = options;
  104. if (context != null) {
  105. typeIdentifiers = context.TypeIdentifiers;
  106. InitSharedData (context);
  107. }
  108. else
  109. typeIdentifiers = new CodeIdentifiers ();
  110. InitializeExtensions ();
  111. }
  112. [MonoTODO]
  113. public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)
  114. {
  115. this.typeIdentifiers = typeIdentifiers;
  116. this.schemas = schemas;
  117. // this.options = options;
  118. InitializeExtensions ();
  119. }
  120. void InitSharedData (ImportContext context)
  121. {
  122. if (context.ShareTypes) {
  123. mappedTypes = context.MappedTypes;
  124. dataMappedTypes = context.DataMappedTypes;
  125. sharedAnonymousTypes = context.SharedAnonymousTypes;
  126. }
  127. }
  128. #endif
  129. internal bool UseEncodedFormat
  130. {
  131. get { return encodedFormat; }
  132. set { encodedFormat = value; }
  133. }
  134. #endregion // Constructors
  135. #region Methods
  136. void InitializeExtensions ()
  137. {
  138. #if NET_2_0 && CONFIGURATION_DEP
  139. SerializationSectionGroup root = ConfigurationManager.GetSection ("system.xml.serialization") as SerializationSectionGroup;
  140. if (root == null)
  141. return;
  142. foreach (SchemaImporterExtensionElement element in
  143. root.SchemaImporterExtensions.SchemaImporterExtensions)
  144. Extensions.Add (element.Name, element.Type);
  145. #endif
  146. }
  147. public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
  148. {
  149. if (typeName == XmlQualifiedName.Empty)
  150. {
  151. XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
  152. mapMem.Name = typeName.Name;
  153. mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
  154. mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None, -1));
  155. XmlMemberMapping[] mm = new XmlMemberMapping [1];
  156. mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
  157. return new XmlMembersMapping (mm);
  158. }
  159. else
  160. {
  161. XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));
  162. if (stype == null)
  163. throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");
  164. if (!CanBeAnyElement (stype))
  165. throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");
  166. ClassMap cmap = new ClassMap ();
  167. CodeIdentifiers classIds = new CodeIdentifiers ();
  168. bool isMixed = stype.IsMixed;
  169. ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);
  170. XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];
  171. mapMem.Name = typeName.Name;
  172. XmlMemberMapping[] mm = new XmlMemberMapping [1];
  173. mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
  174. return new XmlMembersMapping (mm);
  175. }
  176. }
  177. public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
  178. {
  179. return ImportDerivedTypeMapping (name, baseType, true);
  180. }
  181. public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
  182. {
  183. XmlQualifiedName qname;
  184. XmlSchemaType stype;
  185. if (encodedFormat)
  186. {
  187. qname = name;
  188. stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  189. if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
  190. }
  191. else
  192. {
  193. if (!LocateElement (name, out qname, out stype))
  194. return null;
  195. }
  196. XmlTypeMapping map = GetRegisteredTypeMapping (qname, baseType);
  197. if (map != null)
  198. {
  199. // If the type has already been imported, make sure that the map
  200. // has the requested base type
  201. SetMapBaseType (map, baseType);
  202. map.UpdateRoot (name);
  203. return map;
  204. }
  205. map = CreateTypeMapping (qname, SchemaTypes.Class, name);
  206. if (stype != null) {
  207. map.Documentation = GetDocumentation (stype);
  208. RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
  209. } else {
  210. ClassMap cmap = new ClassMap ();
  211. CodeIdentifiers classIds = new CodeIdentifiers ();
  212. map.ObjectMap = cmap;
  213. AddTextMember (qname, cmap, classIds);
  214. }
  215. BuildPendingMaps ();
  216. SetMapBaseType (map, baseType);
  217. return map;
  218. }
  219. void SetMapBaseType (XmlTypeMapping map, Type baseType)
  220. {
  221. // This method sets the base type for a given map.
  222. // If the map already inherits from this type, it does nothing.
  223. // Fiirst of all, check if the map already inherits from baseType
  224. XmlTypeMapping topMap = null;
  225. while (map != null)
  226. {
  227. if (map.TypeData.Type == baseType)
  228. return;
  229. topMap = map;
  230. map = map.BaseMap;
  231. }
  232. // Does not have the requested base type.
  233. // Then, get/create a map for that base type.
  234. XmlTypeMapping baseMap = ReflectType (baseType);
  235. // Add this map as a derived map of the base map
  236. topMap.BaseMap = baseMap;
  237. baseMap.DerivedTypes.Add (topMap);
  238. baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);
  239. // Now add the base type fields to all derived maps
  240. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  241. ClassMap cmap = (ClassMap)topMap.ObjectMap;
  242. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  243. cmap.AddMember (member);
  244. foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)
  245. {
  246. cmap = (ClassMap)derivedMap.ObjectMap;
  247. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  248. cmap.AddMember (member);
  249. }
  250. }
  251. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
  252. {
  253. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  254. if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
  255. XmlSchemaComplexType stype;
  256. if (elem.SchemaType != null)
  257. {
  258. stype = elem.SchemaType as XmlSchemaComplexType;
  259. }
  260. else
  261. {
  262. if (elem.SchemaTypeName.IsEmpty) return null;
  263. object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
  264. if (type == null) {
  265. if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;
  266. throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
  267. }
  268. stype = type as XmlSchemaComplexType;
  269. }
  270. if (stype == null)
  271. throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
  272. XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);
  273. return new XmlMembersMapping (name.Name, name.Namespace, mapping);
  274. }
  275. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
  276. {
  277. XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
  278. for (int n=0; n<names.Length; n++)
  279. {
  280. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
  281. if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
  282. XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
  283. XmlTypeMapping tmap;
  284. TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);
  285. mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap, n);
  286. }
  287. BuildPendingMaps ();
  288. return new XmlMembersMapping (mapping);
  289. }
  290. #if NET_2_0
  291. [MonoTODO]
  292. public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)
  293. {
  294. throw new NotImplementedException ();
  295. }
  296. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)
  297. {
  298. return ImportSchemaType (typeName, typeof (object));
  299. }
  300. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)
  301. {
  302. return ImportSchemaType (typeName, typeof (object), false);
  303. }
  304. [MonoTODO ("baseType and baseTypeCanBeIndirect are ignored")]
  305. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)
  306. {
  307. XmlSchemaType stype =
  308. (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaComplexType)) ??
  309. (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaSimpleType));
  310. return ImportTypeCommon (typeName, typeName, stype, true);
  311. }
  312. #endif
  313. internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
  314. {
  315. XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
  316. for (int n=0; n<members.Length; n++)
  317. {
  318. TypeData td = GetTypeData (members[n].MemberType, null, false); // FIXME: isNullable could be true?
  319. XmlTypeMapping tmap = GetTypeMapping (td);
  320. mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap, n);
  321. }
  322. BuildPendingMaps ();
  323. return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
  324. }
  325. internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
  326. {
  327. XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  328. if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
  329. XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);
  330. return new XmlMembersMapping (name, ns, mapping);
  331. }
  332. XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
  333. {
  334. if (stype.Particle == null)
  335. return new XmlMemberMapping [0];
  336. ClassMap cmap = new ClassMap ();
  337. XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
  338. if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
  339. CodeIdentifiers classIds = new CodeIdentifiers ();
  340. ImportParticleComplexContent (refer, cmap, seq, classIds, false);
  341. ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);
  342. BuildPendingMaps ();
  343. int n = 0;
  344. XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
  345. foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
  346. mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
  347. return mapping;
  348. }
  349. XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap, int order)
  350. {
  351. XmlTypeMapMemberElement mapMem;
  352. if (type.IsListType)
  353. mapMem = new XmlTypeMapMemberList ();
  354. else
  355. mapMem = new XmlTypeMapMemberElement ();
  356. mapMem.Name = name;
  357. mapMem.TypeData = type;
  358. mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap, order));
  359. return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
  360. }
  361. [MonoTODO]
  362. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
  363. {
  364. throw new NotImplementedException ();
  365. }
  366. public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
  367. {
  368. XmlQualifiedName qname;
  369. XmlSchemaType stype;
  370. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  371. if (!LocateElement (elem, out qname, out stype))
  372. throw new InvalidOperationException (String.Format ("'{0}' is missing.", name));
  373. return ImportTypeCommon (name, qname, stype, elem.IsNillable);
  374. }
  375. // FIXME: name and qname are confusing. Rename one either
  376. // (name is in schema itself, qname is for actual processing.
  377. // For example simple types have qname as in xsd namespace.)
  378. private XmlTypeMapping ImportTypeCommon (XmlQualifiedName name, XmlQualifiedName qname, XmlSchemaType stype, bool isNullable)
  379. {
  380. if (stype == null) {
  381. if (qname == anyType) {
  382. // Importing anyType.
  383. XmlTypeMapping xmap = GetTypeMapping (TypeTranslator.GetTypeData (typeof (object)));
  384. // This also means, all complexTypes
  385. // are imported as well.
  386. BuildPendingMaps ();
  387. return xmap;
  388. } else {
  389. // Importing a primitive type
  390. TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);
  391. return ReflectType (td, name.Namespace);
  392. }
  393. }
  394. XmlTypeMapping map = GetRegisteredTypeMapping (qname);
  395. if (map != null) return map;
  396. if (stype is XmlSchemaSimpleType)
  397. return ImportClassSimpleType (stype.QualifiedName, (XmlSchemaSimpleType) stype, name);
  398. map = CreateTypeMapping (qname, SchemaTypes.Class, name);
  399. map.Documentation = GetDocumentation (stype);
  400. map.IsNullable = isNullable;
  401. RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
  402. BuildPendingMaps ();
  403. return map;
  404. }
  405. bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
  406. {
  407. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  408. return LocateElement (elem, out qname, out stype);
  409. }
  410. bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)
  411. {
  412. qname = null;
  413. stype = null;
  414. if (elem == null) return false;
  415. // The root element must be an element with complex type
  416. if (elem.SchemaType != null)
  417. {
  418. stype = elem.SchemaType;
  419. qname = elem.QualifiedName;
  420. }
  421. else if (elem.ElementType == XmlSchemaComplexType.AnyType)
  422. {
  423. qname = anyType;
  424. return true;
  425. }
  426. else
  427. {
  428. if (elem.SchemaTypeName.IsEmpty) return false;
  429. object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
  430. if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
  431. if (type == null) {
  432. if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {
  433. qname = elem.SchemaTypeName;
  434. return true;
  435. }
  436. throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
  437. }
  438. stype = (XmlSchemaType) type;
  439. qname = stype.QualifiedName;
  440. XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;
  441. if (btype != null && btype.QualifiedName == elem.SchemaTypeName)
  442. throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");
  443. }
  444. //if (stype is XmlSchemaSimpleType) return false;
  445. return true;
  446. }
  447. XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)
  448. {
  449. XmlTypeMapping map = GetRegisteredTypeMapping (name);
  450. if (map != null) {
  451. map.UpdateRoot (root);
  452. return map;
  453. }
  454. XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
  455. if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
  456. if (type == null)
  457. {
  458. if (throwOnError) {
  459. if (name.Namespace == XmlSerializer.EncodingNamespace)
  460. throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");
  461. else
  462. throw new InvalidOperationException ("Referenced type '" + name + "' not found.");
  463. } else
  464. return null;
  465. }
  466. return ImportType (name, type, root);
  467. }
  468. XmlTypeMapping ImportClass (XmlQualifiedName name)
  469. {
  470. XmlTypeMapping map = ImportType (name, null, true);
  471. if (map.TypeData.SchemaType == SchemaTypes.Class) return map;
  472. XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  473. return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));
  474. }
  475. XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
  476. {
  477. XmlTypeMapping map = GetRegisteredTypeMapping (name);
  478. if (map != null) {
  479. XmlSchemaComplexType ct = stype as XmlSchemaComplexType;
  480. if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {
  481. map.UpdateRoot (root);
  482. return map;
  483. }
  484. // The map was initially imported as a class, but it turns out that it is an
  485. // array. It has to be imported now as array.
  486. }
  487. if (stype is XmlSchemaComplexType)
  488. return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
  489. else if (stype is XmlSchemaSimpleType)
  490. return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
  491. throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
  492. }
  493. XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
  494. {
  495. // The need for fixups: If the complex type is an array, then to get the type of the
  496. // array we need first to get the type of the items of the array.
  497. // But if one of the item types or its children has a referece to this type array,
  498. // then we enter in an infinite loop. This does not happen with class types because
  499. // the class map is registered before parsing the children. We can't do the same
  500. // with the array type because to register the array map we need the type of the array.
  501. if (CanBeArray (typeQName, stype))
  502. {
  503. TypeData typeData;
  504. ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
  505. if (listMap != null)
  506. {
  507. XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);
  508. map.ObjectMap = listMap;
  509. return map;
  510. }
  511. // After all, it is not an array. Create a class map then.
  512. }
  513. else if (CanBeIXmlSerializable (stype))
  514. {
  515. return ImportXmlSerializableMapping (typeQName.Namespace);
  516. }
  517. // Register the map right now but do not build it,
  518. // This will avoid loops.
  519. return CreateClassMap (typeQName, stype, root);
  520. }
  521. XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
  522. {
  523. XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
  524. map.Documentation = GetDocumentation (stype);
  525. RegisterMapFixup (map, typeQName, stype);
  526. return map;
  527. }
  528. ArrayList fixup_registered_types = new ArrayList ();
  529. void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
  530. {
  531. // This check is introduced for bug #650117, but might be too wide to catch erroneous cases...
  532. if (fixup_registered_types.Contains (stype))
  533. throw new InvalidOperationException (String.Format ("Circular dependency for schema type {0} in namespace {1}", map.ElementName, map.Namespace));
  534. fixup_registered_types.Add (stype);
  535. MapFixup fixup = new MapFixup ();
  536. fixup.Map = map;
  537. fixup.SchemaType = stype;
  538. fixup.TypeName = typeQName;
  539. pendingMaps.Enqueue (fixup);
  540. }
  541. void BuildPendingMaps ()
  542. {
  543. while (pendingMaps.Count > 0) {
  544. MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();
  545. if (fixup.Map.ObjectMap == null) {
  546. BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
  547. if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
  548. }
  549. }
  550. }
  551. void BuildPendingMap (XmlTypeMapping map)
  552. {
  553. if (map.ObjectMap != null) return;
  554. foreach (MapFixup fixup in pendingMaps)
  555. {
  556. if (fixup.Map == map) {
  557. BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
  558. return;
  559. }
  560. }
  561. throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
  562. }
  563. void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
  564. {
  565. CodeIdentifiers classIds = new CodeIdentifiers();
  566. classIds.AddReserved (map.TypeData.TypeName);
  567. ClassMap cmap = new ClassMap ();
  568. map.ObjectMap = cmap;
  569. bool isMixed = stype.IsMixed;
  570. if (stype.Particle != null)
  571. ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
  572. else
  573. {
  574. if (stype.ContentModel is XmlSchemaSimpleContent) {
  575. ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
  576. }
  577. else if (stype.ContentModel is XmlSchemaComplexContent) {
  578. ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
  579. }
  580. }
  581. ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
  582. ImportExtensionTypes (typeQName);
  583. if (isMixed) AddTextMember (typeQName, cmap, classIds);
  584. AddObjectDerivedMap (map);
  585. }
  586. void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
  587. {
  588. atts = CollectAttributeUsesNonOverlap (atts, cmap);
  589. if (anyat != null)
  590. {
  591. XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
  592. member.Name = classIds.AddUnique ("AnyAttribute", member);
  593. member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
  594. cmap.AddMember (member);
  595. }
  596. foreach (XmlSchemaObject at in atts)
  597. {
  598. if (at is XmlSchemaAttribute)
  599. {
  600. string ns;
  601. XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
  602. XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
  603. XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
  604. member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
  605. member.Documentation = GetDocumentation (attr);
  606. member.AttributeName = refAttr.Name;
  607. member.Namespace = ns;
  608. member.Form = refAttr.Form;
  609. member.TypeData = GetAttributeTypeData (typeQName, attr);
  610. if (refAttr.DefaultValue != null)
  611. member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);
  612. else if (member.TypeData.IsValueType)
  613. member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);
  614. if (member.TypeData.IsComplexType)
  615. member.MappedType = GetTypeMapping (member.TypeData);
  616. cmap.AddMember (member);
  617. }
  618. else if (at is XmlSchemaAttributeGroupRef)
  619. {
  620. XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
  621. XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
  622. ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
  623. }
  624. }
  625. }
  626. // Attributes might be redefined, so there is an existing attribute for the same name, skip it.
  627. // FIXME: this is nothing more than just a hack.
  628. // Basically it should use
  629. // XmlSchemaComplexType.AttributeUses.
  630. XmlSchemaObjectCollection CollectAttributeUsesNonOverlap (
  631. XmlSchemaObjectCollection src, ClassMap map)
  632. {
  633. XmlSchemaObjectCollection atts = new XmlSchemaObjectCollection ();
  634. foreach (XmlSchemaAttribute a in src)
  635. if (map.GetAttribute (a.QualifiedName.Name, a.QualifiedName.Namespace) == null)
  636. atts.Add (a);
  637. return atts;
  638. }
  639. ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
  640. {
  641. if (encodedFormat)
  642. {
  643. XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
  644. XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
  645. XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
  646. if (arrayTypeAt != null)
  647. {
  648. XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
  649. if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
  650. XmlAttribute xat = null;
  651. foreach (XmlAttribute at in uatts)
  652. if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
  653. { xat = at; break; }
  654. if (xat == null)
  655. throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
  656. string name, ns, dims;
  657. TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
  658. return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
  659. }
  660. else
  661. {
  662. XmlSchemaElement elem = null;
  663. XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
  664. if (seq != null && seq.Items.Count == 1)
  665. elem = seq.Items[0] as XmlSchemaElement;
  666. else {
  667. XmlSchemaAll all = rest.Particle as XmlSchemaAll;
  668. if (all != null && all.Items.Count == 1)
  669. elem = all.Items[0] as XmlSchemaElement;
  670. }
  671. if (elem == null)
  672. throw new InvalidOperationException ("Unknown array format");
  673. return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
  674. }
  675. }
  676. else
  677. {
  678. ClassMap cmap = new ClassMap ();
  679. CodeIdentifiers classIds = new CodeIdentifiers();
  680. ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);
  681. XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
  682. if (list != null && list.ChoiceMember == null)
  683. {
  684. arrayTypeData = list.TypeData;
  685. return list.ListMap;
  686. }
  687. else
  688. {
  689. arrayTypeData = null;
  690. return null;
  691. }
  692. }
  693. }
  694. ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
  695. {
  696. ListMap map = new ListMap ();
  697. int i = type.LastIndexOf ("[");
  698. if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
  699. if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
  700. string itemType = type.Substring (0,i);
  701. TypeData itemTypeData;
  702. if (itemType.IndexOf ("[") != -1)
  703. {
  704. ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
  705. int dims = itemType.Split ('[').Length - 1;
  706. string name = TypeTranslator.GetArrayName (type, dims);
  707. XmlQualifiedName qname = new XmlQualifiedName (name, ns);
  708. XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
  709. tmap.ObjectMap = innerListMap;
  710. }
  711. else
  712. {
  713. itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null, false);
  714. }
  715. arrayTypeData = itemTypeData.ListTypeData;
  716. map.ItemInfo = new XmlTypeMapElementInfoList();
  717. map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None, -1));
  718. return map;
  719. }
  720. XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
  721. {
  722. foreach (object ob in atts)
  723. {
  724. XmlSchemaAttribute att = ob as XmlSchemaAttribute;
  725. if (att != null && att.RefName == arrayTypeRefName) return att;
  726. XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
  727. if (gref != null)
  728. {
  729. XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
  730. att = FindArrayAttribute (grp.Attributes);
  731. if (att != null) return att;
  732. }
  733. }
  734. return null;
  735. }
  736. void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
  737. {
  738. ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
  739. if (isMixed) AddTextMember (typeQName, cmap, classIds);
  740. }
  741. void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)
  742. {
  743. if (cmap.XmlTextCollector == null)
  744. {
  745. XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
  746. member.Name = classIds.AddUnique ("Text", member);
  747. member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
  748. member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
  749. member.IsXmlTextCollector = true;
  750. member.ListMap = new ListMap ();
  751. member.ListMap.ItemInfo = member.ElementInfo;
  752. cmap.AddMember (member);
  753. }
  754. }
  755. void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
  756. {
  757. if (particle == null) return;
  758. if (particle is XmlSchemaGroupRef)
  759. particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
  760. if (particle.MaxOccurs > 1) multiValue = true;
  761. if (particle is XmlSchemaSequence) {
  762. ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
  763. }
  764. else if (particle is XmlSchemaChoice) {
  765. if (((XmlSchemaChoice)particle).Items.Count == 1)
  766. ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
  767. else
  768. ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
  769. }
  770. else if (particle is XmlSchemaAll) {
  771. ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
  772. }
  773. }
  774. void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
  775. {
  776. foreach (XmlSchemaObject item in items)
  777. {
  778. if (item is XmlSchemaElement)
  779. {
  780. string ns;
  781. XmlSchemaElement elem = (XmlSchemaElement) item;
  782. XmlTypeMapping emap;
  783. TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
  784. XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
  785. if (elem.MaxOccurs == 1 && !multiValue)
  786. {
  787. XmlTypeMapMemberElement member = null;
  788. if (typeData.SchemaType != SchemaTypes.Array)
  789. {
  790. member = new XmlTypeMapMemberElement ();
  791. if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);
  792. }
  793. else if (GetTypeMapping (typeData).IsSimpleType)
  794. {
  795. // It is a simple list (space separated list).
  796. // Since this is not supported, map as a single item value
  797. member = new XmlTypeMapMemberElement ();
  798. #if NET_2_0
  799. // In MS.NET those types are mapped to a string
  800. typeData = TypeTranslator.GetTypeData(typeof(string));
  801. #else
  802. typeData = typeData.ListItemTypeData;
  803. #endif
  804. }
  805. else
  806. member = new XmlTypeMapMemberList ();
  807. if (elem.MinOccurs == 0 && typeData.IsValueType)
  808. member.IsOptionalValueType = true;
  809. member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
  810. member.Documentation = GetDocumentation (elem);
  811. member.TypeData = typeData;
  812. member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, items.IndexOf (item)));
  813. cmap.AddMember (member);
  814. }
  815. else
  816. {
  817. XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
  818. member.ListMap = new ListMap ();
  819. member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
  820. member.Documentation = GetDocumentation (elem);
  821. member.TypeData = typeData.ListTypeData;
  822. member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, items.IndexOf (item)));
  823. member.ListMap.ItemInfo = member.ElementInfo;
  824. cmap.AddMember (member);
  825. }
  826. }
  827. else if (item is XmlSchemaAny)
  828. {
  829. XmlSchemaAny elem = (XmlSchemaAny) item;
  830. XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
  831. member.Name = classIds.AddUnique ("Any", member);
  832. member.Documentation = GetDocumentation (elem);
  833. Type ctype;
  834. if (elem.MaxOccurs != 1 || multiValue)
  835. ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
  836. else
  837. ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
  838. member.TypeData = TypeTranslator.GetTypeData (ctype);
  839. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
  840. einfo.IsUnnamedAnyElement = true;
  841. member.ElementInfo.Add (einfo);
  842. if (isMixed)
  843. {
  844. einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
  845. member.ElementInfo.Add (einfo);
  846. member.IsXmlTextCollector = true;
  847. isMixed = false; //Allow only one XmlTextAttribute
  848. }
  849. cmap.AddMember (member);
  850. }
  851. else if (item is XmlSchemaParticle) {
  852. ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
  853. }
  854. }
  855. }
  856. object ImportDefaultValue (TypeData typeData, string value)
  857. {
  858. if (typeData.SchemaType == SchemaTypes.Enum) {
  859. XmlTypeMapping map = GetTypeMapping (typeData);
  860. EnumMap emap = (EnumMap) map.ObjectMap;
  861. string res = emap.GetEnumName (map.TypeFullName, value);
  862. if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
  863. return res;
  864. } else
  865. return XmlCustomFormatter.FromXmlString (typeData, value);
  866. }
  867. void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
  868. {
  869. XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
  870. multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
  871. if (choices.Count == 0) return;
  872. if (choice.MaxOccurs > 1) multiValue = true;
  873. XmlTypeMapMemberElement member;
  874. if (multiValue)
  875. {
  876. member = new XmlTypeMapMemberFlatList ();
  877. member.Name = classIds.AddUnique ("Items", member);
  878. ListMap listMap = new ListMap ();
  879. listMap.ItemInfo = choices;
  880. ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
  881. }
  882. else
  883. {
  884. member = new XmlTypeMapMemberElement ();
  885. member.Name = classIds.AddUnique ("Item", member);
  886. }
  887. // If all choices have the same type, use that type for the member.
  888. // If not use System.Object.
  889. // If there are at least two choices with the same type, use a choice
  890. // identifier attribute
  891. TypeData typeData = null;
  892. bool twoEqual = false;
  893. bool allEqual = true;
  894. Hashtable types = new Hashtable ();
  895. for (int n = choices.Count - 1; n >= 0; n--)
  896. {
  897. XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];
  898. // In some complex schemas, we may end up with several options
  899. // with the same name. It is better to ignore the extra options
  900. // than to crash. It's the best we can do, and btw it works
  901. // better than in MS.NET.
  902. if (cmap.GetElement (einfo.ElementName, einfo.Namespace, einfo.ExplicitOrder) != null ||
  903. choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)
  904. {
  905. choices.RemoveAt (n);
  906. continue;
  907. }
  908. if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
  909. else types.Add (einfo.TypeData, einfo);
  910. TypeData choiceType = einfo.TypeData;
  911. if (choiceType.SchemaType == SchemaTypes.Class)
  912. {
  913. // When comparing class types, use the most generic class in the
  914. // inheritance hierarchy
  915. XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
  916. BuildPendingMap (choiceMap);
  917. while (choiceMap.BaseMap != null) {
  918. choiceMap = choiceMap.BaseMap;
  919. BuildPendingMap (choiceMap);
  920. choiceType = choiceMap.TypeData;
  921. }
  922. }
  923. if (typeData == null) typeData = choiceType;
  924. else if (typeData != choiceType) allEqual = false;
  925. }
  926. if (!allEqual)
  927. typeData = TypeTranslator.GetTypeData (typeof(object));
  928. if (twoEqual)
  929. {
  930. // Create the choice member
  931. XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
  932. choiceMember.Ignore = true;
  933. choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
  934. member.ChoiceMember = choiceMember.Name;
  935. // Create the choice enum
  936. XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
  937. enumMap.IncludeInSchema = false;
  938. CodeIdentifiers codeIdents = new CodeIdentifiers ();
  939. EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
  940. for (int n=0; n<choices.Count; n++)
  941. {
  942. XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
  943. bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);
  944. string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;
  945. string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
  946. members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
  947. }
  948. enumMap.ObjectMap = new EnumMap (members, false);
  949. choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
  950. choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None, -1));
  951. cmap.AddMember (choiceMember);
  952. }
  953. if (typeData == null)
  954. return;
  955. if (multiValue)
  956. typeData = typeData.ListTypeData;
  957. member.ElementInfo = choices;
  958. member.Documentation = GetDocumentation (choice);
  959. member.TypeData = typeData;
  960. cmap.AddMember (member);
  961. }
  962. bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
  963. {
  964. bool multiValue = false;
  965. foreach (XmlSchemaObject titem in items)
  966. {
  967. XmlSchemaObject item = titem;
  968. if (item is XmlSchemaGroupRef)
  969. item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
  970. if (item is XmlSchemaElement)
  971. {
  972. string ns;
  973. XmlSchemaElement elem = (XmlSchemaElement) item;
  974. XmlTypeMapping emap;
  975. TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
  976. XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
  977. choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, -1));
  978. if (elem.MaxOccurs > 1) multiValue = true;
  979. }
  980. else if (item is XmlSchemaAny)
  981. {
  982. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
  983. einfo.IsUnnamedAnyElement = true;
  984. choices.Add (einfo);
  985. }
  986. else if (item is XmlSchemaChoice) {
  987. multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
  988. }
  989. else if (item is XmlSchemaSequence) {
  990. multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
  991. }
  992. }
  993. return multiValue;
  994. }
  995. void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
  996. {
  997. XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
  998. ClassMap cmap = (ClassMap)map.ObjectMap;
  999. XmlQualifiedName qname = GetContentBaseType (content.Content);
  1000. TypeData simpleType = null;
  1001. if (!IsPrimitiveTypeNamespace (qname.Namespace))
  1002. {
  1003. // Add base map members to this map
  1004. XmlTypeMapping baseMap = ImportType (qname, null, true);
  1005. BuildPendingMap (baseMap);
  1006. if (baseMap.IsSimpleType) {
  1007. simpleType = baseMap.TypeData;
  1008. } else {
  1009. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  1010. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  1011. cmap.AddMember (member);
  1012. map.BaseMap = baseMap;
  1013. baseMap.DerivedTypes.Add (map);
  1014. }
  1015. }
  1016. else
  1017. simpleType = FindBuiltInType (qname);
  1018. if (simpleType != null) {
  1019. XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
  1020. member.Name = classIds.AddUnique("Value", member);
  1021. member.TypeData = simpleType;
  1022. member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
  1023. member.IsXmlTextCollector = true;
  1024. cmap.AddMember (member);
  1025. }
  1026. if (ext != null)
  1027. ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
  1028. }
  1029. TypeData FindBuiltInType (XmlQualifiedName qname)
  1030. {
  1031. XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
  1032. if (ct != null)
  1033. {
  1034. XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
  1035. if (sc == null) throw new InvalidOperationException ("Invalid schema");
  1036. return FindBuiltInType (GetContentBaseType (sc.Content));
  1037. }
  1038. XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
  1039. if (st != null)
  1040. return FindBuiltInType (qname, st);
  1041. if (IsPrimitiveTypeNamespace (qname.Namespace))
  1042. return TypeTranslator.GetPrimitiveTypeData (qname.Name);
  1043. throw new InvalidOperationException ("Definition of type '" + qname + "' not found");
  1044. }
  1045. TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
  1046. {
  1047. if (CanBeEnum (st) && qname != null)
  1048. return ImportType (qname, null, true).TypeData;
  1049. if (st.Content is XmlSchemaSimpleTypeRestriction) {
  1050. XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;
  1051. XmlQualifiedName bn = GetContentBaseType (rest);
  1052. if (bn == XmlQualifiedName.Empty && rest.BaseType != null)
  1053. return FindBuiltInType (qname, rest.BaseType);
  1054. else
  1055. return FindBuiltInType (bn);
  1056. }
  1057. else if (st.Content is XmlSchemaSimpleTypeList) {
  1058. return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
  1059. }
  1060. else if (st.Content is XmlSchemaSimpleTypeUnion) {
  1061. // MS.NET always import simple unions as string
  1062. return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema.Namespace));
  1063. }
  1064. else
  1065. return null;
  1066. }
  1067. XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
  1068. {
  1069. if (ob is XmlSchemaSimpleContentExtension)
  1070. return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
  1071. else if (ob is XmlSchemaSimpleContentRestriction)
  1072. return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
  1073. else if (ob is XmlSchemaSimpleTypeRestriction)
  1074. return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
  1075. else if (ob is XmlSchemaSimpleTypeList)
  1076. return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
  1077. else
  1078. return null;
  1079. }
  1080. void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
  1081. {
  1082. ClassMap cmap = (ClassMap)map.ObjectMap;
  1083. XmlQualifiedName qname;
  1084. XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
  1085. if (ext != null) qname = ext.BaseTypeName;
  1086. else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
  1087. if (qname == typeQName)
  1088. throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");
  1089. // Add base map members to this map
  1090. XmlTypeMapping baseMap = ImportClass (qname);
  1091. BuildPendingMap (baseMap);
  1092. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  1093. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  1094. cmap.AddMember (member);
  1095. if (baseClassMap.XmlTextCollector != null) isMixed = false;
  1096. else if (content.IsMixed) isMixed = true;
  1097. map.BaseMap = baseMap;
  1098. baseMap.DerivedTypes.Add (map);
  1099. if (ext != null) {
  1100. // Add the members of this map
  1101. ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
  1102. ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
  1103. }
  1104. else {
  1105. if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
  1106. }
  1107. }
  1108. void ImportExtensionTypes (XmlQualifiedName qname)
  1109. {
  1110. foreach (XmlSchema schema in schemas) {
  1111. foreach (XmlSchemaObject sob in schema.Items)
  1112. {
  1113. XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
  1114. if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
  1115. XmlQualifiedName exqname;
  1116. XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
  1117. if (ext != null) exqname = ext.BaseTypeName;
  1118. else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
  1119. if (exqname == qname)
  1120. ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
  1121. }
  1122. }
  1123. }
  1124. }
  1125. XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
  1126. {
  1127. if (CanBeEnum (stype))
  1128. {
  1129. // Create an enum map
  1130. CodeIdentifiers codeIdents = new CodeIdentifiers ();
  1131. XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, root);
  1132. enumMap.Documentation = GetDocumentation (stype);
  1133. bool isFlags = false;
  1134. if (stype.Content is XmlSchemaSimpleTypeList) {
  1135. stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
  1136. isFlags = true;
  1137. }
  1138. XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
  1139. codeIdents.AddReserved (enumMap.TypeData.TypeName);
  1140. EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
  1141. for (int n=0; n<rest.Facets.Count; n++)
  1142. {
  1143. XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
  1144. string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
  1145. members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
  1146. members [n].Documentation = GetDocumentation (enu);
  1147. }
  1148. enumMap.ObjectMap = new EnumMap (members, isFlags);
  1149. enumMap.IsSimpleType = true;
  1150. return enumMap;
  1151. }
  1152. if (stype.Content is XmlSchemaSimpleTypeList)
  1153. {
  1154. XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
  1155. TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
  1156. ListMap listMap = new ListMap ();
  1157. listMap.ItemInfo = new XmlTypeMapElementInfoList ();
  1158. listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None, -1));
  1159. XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
  1160. map.ObjectMap = listMap;
  1161. map.IsSimpleType = true;
  1162. return map;
  1163. }
  1164. // It is an extension of a primitive or known type
  1165. TypeData typeData = FindBuiltInType (typeQName, stype);
  1166. XmlTypeMapping rmap = GetTypeMapping (typeData);
  1167. // The resulting map must be a simple type. It needs to be explicitely set for arrays
  1168. rmap.IsSimpleType = true;
  1169. return r

Large files files are truncated, but you can click here to view the full file