XmlSchemaImporter.cs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851
  1. //
  2. // System.Xml.Serialization.XmlSchemaImporter
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  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. using System.CodeDom.Compiler;
  32. using System.Xml.Schema;
  33. using System.Collections;
  34. namespace System.Xml.Serialization
  35. {
  36. public class XmlSchemaImporter
  37. #if NET_2_0
  38. : SchemaImporter
  39. #endif
  40. {
  41. #region Fields
  42. XmlSchemas schemas;
  43. CodeIdentifiers typeIdentifiers;
  44. CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
  45. Hashtable mappedTypes = new Hashtable ();
  46. Hashtable dataMappedTypes = new Hashtable ();
  47. Queue pendingMaps = new Queue ();
  48. Hashtable sharedAnonymousTypes = new Hashtable ();
  49. bool encodedFormat = false;
  50. XmlReflectionImporter auxXmlRefImporter;
  51. SoapReflectionImporter auxSoapRefImporter;
  52. bool anyTypeImported;
  53. #if NET_2_0
  54. CodeGenerationOptions options;
  55. #endif
  56. static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
  57. static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
  58. static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
  59. const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
  60. XmlSchemaElement anyElement = null;
  61. class MapFixup
  62. {
  63. public XmlTypeMapping Map;
  64. public XmlSchemaComplexType SchemaType;
  65. public XmlQualifiedName TypeName;
  66. }
  67. #endregion
  68. #region Constructors
  69. public XmlSchemaImporter (XmlSchemas schemas)
  70. {
  71. this.schemas = schemas;
  72. typeIdentifiers = new CodeIdentifiers ();
  73. }
  74. public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
  75. : this (schemas)
  76. {
  77. this.typeIdentifiers = typeIdentifiers;
  78. }
  79. #if NET_2_0
  80. [MonoTODO]
  81. public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)
  82. {
  83. this.schemas = schemas;
  84. this.options = options;
  85. if (context != null) {
  86. typeIdentifiers = context.TypeIdentifiers;
  87. InitSharedData (context);
  88. }
  89. else
  90. typeIdentifiers = new CodeIdentifiers ();
  91. }
  92. public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)
  93. {
  94. this.schemas = schemas;
  95. this.options = options;
  96. if (context != null) {
  97. typeIdentifiers = context.TypeIdentifiers;
  98. InitSharedData (context);
  99. }
  100. else
  101. typeIdentifiers = new CodeIdentifiers ();
  102. }
  103. public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)
  104. {
  105. this.typeIdentifiers = typeIdentifiers;
  106. this.schemas = schemas;
  107. this.options = options;
  108. }
  109. void InitSharedData (ImportContext context)
  110. {
  111. if (context.ShareTypes) {
  112. mappedTypes = context.MappedTypes;
  113. dataMappedTypes = context.DataMappedTypes;
  114. sharedAnonymousTypes = context.SharedAnonymousTypes;
  115. }
  116. }
  117. #endif
  118. internal bool UseEncodedFormat
  119. {
  120. get { return encodedFormat; }
  121. set { encodedFormat = value; }
  122. }
  123. #endregion // Constructors
  124. #region Methods
  125. public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
  126. {
  127. if (typeName == XmlQualifiedName.Empty)
  128. {
  129. XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
  130. mapMem.Name = typeName.Name;
  131. mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
  132. mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None));
  133. XmlMemberMapping[] mm = new XmlMemberMapping [1];
  134. mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
  135. return new XmlMembersMapping (mm);
  136. }
  137. else
  138. {
  139. XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));
  140. if (stype == null)
  141. throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");
  142. if (!CanBeAnyElement (stype))
  143. throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");
  144. ClassMap cmap = new ClassMap ();
  145. CodeIdentifiers classIds = new CodeIdentifiers ();
  146. bool isMixed = stype.IsMixed;
  147. ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);
  148. XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];
  149. mapMem.Name = typeName.Name;
  150. XmlMemberMapping[] mm = new XmlMemberMapping [1];
  151. mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
  152. return new XmlMembersMapping (mm);
  153. }
  154. }
  155. public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
  156. {
  157. return ImportDerivedTypeMapping (name, baseType, true);
  158. }
  159. public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
  160. {
  161. XmlQualifiedName qname;
  162. XmlSchemaType stype;
  163. if (encodedFormat)
  164. {
  165. qname = name;
  166. stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  167. if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
  168. }
  169. else
  170. {
  171. if (!LocateElement (name, out qname, out stype))
  172. return null;
  173. }
  174. XmlTypeMapping map = GetRegisteredTypeMapping (qname);
  175. if (map != null)
  176. {
  177. // If the type has already been imported, make sure that the map
  178. // has the requested base type
  179. SetMapBaseType (map, baseType);
  180. map.UpdateRoot (name);
  181. return map;
  182. }
  183. map = CreateTypeMapping (qname, SchemaTypes.Class, name);
  184. if (stype != null) {
  185. map.Documentation = GetDocumentation (stype);
  186. RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
  187. } else {
  188. ClassMap cmap = new ClassMap ();
  189. CodeIdentifiers classIds = new CodeIdentifiers ();
  190. map.ObjectMap = cmap;
  191. AddTextMember (qname, cmap, classIds);
  192. }
  193. BuildPendingMaps ();
  194. SetMapBaseType (map, baseType);
  195. return map;
  196. }
  197. void SetMapBaseType (XmlTypeMapping map, Type baseType)
  198. {
  199. // This method sets the base type for a given map.
  200. // If the map already inherits from this type, it does nothing.
  201. // Fiirst of all, check if the map already inherits from baseType
  202. XmlTypeMapping topMap = null;
  203. while (map != null)
  204. {
  205. if (map.TypeData.Type == baseType)
  206. return;
  207. topMap = map;
  208. map = map.BaseMap;
  209. }
  210. // Does not have the requested base type.
  211. // Then, get/create a map for that base type.
  212. XmlTypeMapping baseMap = ReflectType (baseType);
  213. // Add this map as a derived map of the base map
  214. topMap.BaseMap = baseMap;
  215. baseMap.DerivedTypes.Add (topMap);
  216. baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);
  217. // Now add the base type fields to all derived maps
  218. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  219. ClassMap cmap = (ClassMap)topMap.ObjectMap;
  220. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  221. cmap.AddMember (member);
  222. foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)
  223. {
  224. cmap = (ClassMap)derivedMap.ObjectMap;
  225. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  226. cmap.AddMember (member);
  227. }
  228. }
  229. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
  230. {
  231. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  232. if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
  233. XmlSchemaComplexType stype;
  234. if (elem.SchemaType != null)
  235. {
  236. stype = elem.SchemaType as XmlSchemaComplexType;
  237. }
  238. else
  239. {
  240. if (elem.SchemaTypeName.IsEmpty) return null;
  241. object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
  242. if (type == null) {
  243. if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;
  244. throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
  245. }
  246. stype = type as XmlSchemaComplexType;
  247. }
  248. if (stype == null)
  249. throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
  250. XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);
  251. return new XmlMembersMapping (name.Name, name.Namespace, mapping);
  252. }
  253. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
  254. {
  255. XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
  256. for (int n=0; n<names.Length; n++)
  257. {
  258. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
  259. if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
  260. XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
  261. XmlTypeMapping tmap;
  262. TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);
  263. mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap);
  264. }
  265. BuildPendingMaps ();
  266. return new XmlMembersMapping (mapping);
  267. }
  268. #if NET_2_0
  269. [MonoTODO]
  270. public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)
  271. {
  272. throw new NotImplementedException ();
  273. }
  274. [MonoTODO]
  275. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)
  276. {
  277. throw new NotImplementedException ();
  278. }
  279. [MonoTODO]
  280. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)
  281. {
  282. throw new NotImplementedException ();
  283. }
  284. [MonoTODO]
  285. public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)
  286. {
  287. throw new NotImplementedException ();
  288. }
  289. #endif
  290. internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
  291. {
  292. XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
  293. for (int n=0; n<members.Length; n++)
  294. {
  295. TypeData td = GetTypeData (members[n].MemberType, null);
  296. XmlTypeMapping tmap = GetTypeMapping (td);
  297. mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap);
  298. }
  299. BuildPendingMaps ();
  300. return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
  301. }
  302. internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
  303. {
  304. XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  305. if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
  306. XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);
  307. return new XmlMembersMapping (name, ns, mapping);
  308. }
  309. XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
  310. {
  311. if (stype.Particle == null)
  312. return new XmlMemberMapping [0];
  313. ClassMap cmap = new ClassMap ();
  314. XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
  315. if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
  316. CodeIdentifiers classIds = new CodeIdentifiers ();
  317. ImportParticleComplexContent (refer, cmap, seq, classIds, false);
  318. ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);
  319. BuildPendingMaps ();
  320. int n = 0;
  321. XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
  322. foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
  323. mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
  324. return mapping;
  325. }
  326. XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap)
  327. {
  328. XmlTypeMapMemberElement mapMem;
  329. if (type.IsListType)
  330. mapMem = new XmlTypeMapMemberList ();
  331. else
  332. mapMem = new XmlTypeMapMemberElement ();
  333. mapMem.Name = name;
  334. mapMem.TypeData = type;
  335. mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap));
  336. return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
  337. }
  338. [MonoTODO]
  339. public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
  340. {
  341. throw new NotImplementedException ();
  342. }
  343. public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
  344. {
  345. XmlQualifiedName qname;
  346. XmlSchemaType stype;
  347. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  348. if (!LocateElement (elem, out qname, out stype)) return null;
  349. if (stype == null) {
  350. // Importing a primitive type
  351. TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);
  352. return ReflectType (td, name.Namespace);
  353. }
  354. XmlTypeMapping map = GetRegisteredTypeMapping (qname);
  355. if (map != null) return map;
  356. map = CreateTypeMapping (qname, SchemaTypes.Class, name);
  357. map.Documentation = GetDocumentation (stype);
  358. map.IsNullable = elem.IsNillable;
  359. RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
  360. BuildPendingMaps ();
  361. return map;
  362. }
  363. bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
  364. {
  365. XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
  366. return LocateElement (elem, out qname, out stype);
  367. }
  368. bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)
  369. {
  370. qname = null;
  371. stype = null;
  372. if (elem == null) return false;
  373. // The root element must be an element with complex type
  374. if (elem.SchemaType != null)
  375. {
  376. stype = elem.SchemaType;
  377. qname = elem.QualifiedName;
  378. }
  379. else
  380. {
  381. if (elem.SchemaTypeName.IsEmpty) return false;
  382. object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
  383. if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
  384. if (type == null) {
  385. if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {
  386. qname = elem.SchemaTypeName;
  387. return true;
  388. }
  389. throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
  390. }
  391. stype = (XmlSchemaType) type;
  392. qname = stype.QualifiedName;
  393. XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;
  394. if (btype != null && btype.QualifiedName == elem.SchemaTypeName)
  395. throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");
  396. }
  397. if (stype is XmlSchemaSimpleType) return false;
  398. return true;
  399. }
  400. XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)
  401. {
  402. XmlTypeMapping map = GetRegisteredTypeMapping (name);
  403. if (map != null) {
  404. map.UpdateRoot (root);
  405. return map;
  406. }
  407. XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
  408. if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
  409. if (type == null)
  410. {
  411. if (throwOnError) {
  412. if (name.Namespace == XmlSerializer.EncodingNamespace)
  413. throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");
  414. else
  415. throw new InvalidOperationException ("Referenced type '" + name + "' not found.");
  416. } else
  417. return null;
  418. }
  419. return ImportType (name, type, root);
  420. }
  421. XmlTypeMapping ImportClass (XmlQualifiedName name)
  422. {
  423. XmlTypeMapping map = ImportType (name, null, true);
  424. if (map.TypeData.SchemaType == SchemaTypes.Class) return map;
  425. XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
  426. return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));
  427. }
  428. XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
  429. {
  430. XmlTypeMapping map = GetRegisteredTypeMapping (name);
  431. if (map != null) {
  432. XmlSchemaComplexType ct = stype as XmlSchemaComplexType;
  433. if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {
  434. map.UpdateRoot (root);
  435. return map;
  436. }
  437. // The map was initially imported as a class, but it turns out that it is an
  438. // array. It has to be imported now as array.
  439. }
  440. if (stype is XmlSchemaComplexType)
  441. return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
  442. else if (stype is XmlSchemaSimpleType)
  443. return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
  444. throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
  445. }
  446. XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
  447. {
  448. // The need for fixups: If the complex type is an array, then to get the type of the
  449. // array we need first to get the type of the items of the array.
  450. // But if one of the item types or its children has a referece to this type array,
  451. // then we enter in an infinite loop. This does not happen with class types because
  452. // the class map is registered before parsing the children. We can't do the same
  453. // with the array type because to register the array map we need the type of the array.
  454. Type anyType = GetAnyElementType (stype);
  455. if (anyType != null)
  456. return GetTypeMapping (TypeTranslator.GetTypeData(anyType));
  457. if (CanBeArray (typeQName, stype))
  458. {
  459. TypeData typeData;
  460. ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
  461. if (listMap != null)
  462. {
  463. XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);
  464. map.ObjectMap = listMap;
  465. return map;
  466. }
  467. // After all, it is not an array. Create a class map then.
  468. }
  469. else if (CanBeIXmlSerializable (stype))
  470. {
  471. return ImportXmlSerializableMapping (typeQName.Namespace);
  472. }
  473. // Register the map right now but do not build it,
  474. // This will avoid loops.
  475. return CreateClassMap (typeQName, stype, root);
  476. }
  477. XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
  478. {
  479. XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
  480. map.Documentation = GetDocumentation (stype);
  481. RegisterMapFixup (map, typeQName, stype);
  482. return map;
  483. }
  484. void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
  485. {
  486. MapFixup fixup = new MapFixup ();
  487. fixup.Map = map;
  488. fixup.SchemaType = stype;
  489. fixup.TypeName = typeQName;
  490. pendingMaps.Enqueue (fixup);
  491. }
  492. void BuildPendingMaps ()
  493. {
  494. while (pendingMaps.Count > 0) {
  495. MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();
  496. if (fixup.Map.ObjectMap == null) {
  497. BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
  498. if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
  499. }
  500. }
  501. }
  502. void BuildPendingMap (XmlTypeMapping map)
  503. {
  504. if (map.ObjectMap != null) return;
  505. foreach (MapFixup fixup in pendingMaps)
  506. {
  507. if (fixup.Map == map) {
  508. BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
  509. return;
  510. }
  511. }
  512. throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
  513. }
  514. void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
  515. {
  516. CodeIdentifiers classIds = new CodeIdentifiers();
  517. classIds.AddReserved (map.TypeData.TypeName);
  518. ClassMap cmap = new ClassMap ();
  519. map.ObjectMap = cmap;
  520. bool isMixed = stype.IsMixed;
  521. if (stype.Particle != null)
  522. ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
  523. else
  524. {
  525. if (stype.ContentModel is XmlSchemaSimpleContent) {
  526. ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
  527. }
  528. else if (stype.ContentModel is XmlSchemaComplexContent) {
  529. ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
  530. }
  531. }
  532. ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
  533. ImportExtensionTypes (typeQName);
  534. if (isMixed) AddTextMember (typeQName, cmap, classIds);
  535. AddObjectDerivedMap (map);
  536. }
  537. void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
  538. {
  539. if (anyat != null)
  540. {
  541. XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
  542. member.Name = classIds.AddUnique ("AnyAttribute", member);
  543. member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
  544. cmap.AddMember (member);
  545. }
  546. foreach (XmlSchemaObject at in atts)
  547. {
  548. if (at is XmlSchemaAttribute)
  549. {
  550. string ns;
  551. XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
  552. XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
  553. XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
  554. member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
  555. member.Documentation = GetDocumentation (attr);
  556. member.AttributeName = refAttr.Name;
  557. member.Namespace = ns;
  558. member.Form = refAttr.Form;
  559. member.TypeData = GetAttributeTypeData (typeQName, attr);
  560. if (refAttr.DefaultValue != null)
  561. member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);
  562. else if (member.TypeData.IsValueType)
  563. member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);
  564. if (member.TypeData.IsComplexType)
  565. member.MappedType = GetTypeMapping (member.TypeData);
  566. cmap.AddMember (member);
  567. }
  568. else if (at is XmlSchemaAttributeGroupRef)
  569. {
  570. XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
  571. XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
  572. ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
  573. }
  574. }
  575. }
  576. ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
  577. {
  578. if (encodedFormat)
  579. {
  580. XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
  581. XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
  582. XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
  583. if (arrayTypeAt != null)
  584. {
  585. XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
  586. if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
  587. XmlAttribute xat = null;
  588. foreach (XmlAttribute at in uatts)
  589. if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
  590. { xat = at; break; }
  591. if (xat == null)
  592. throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
  593. string name, ns, dims;
  594. TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
  595. return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
  596. }
  597. else
  598. {
  599. XmlSchemaElement elem = null;
  600. XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
  601. if (seq != null && seq.Items.Count == 1)
  602. elem = seq.Items[0] as XmlSchemaElement;
  603. else {
  604. XmlSchemaAll all = rest.Particle as XmlSchemaAll;
  605. if (all != null && all.Items.Count == 1)
  606. elem = all.Items[0] as XmlSchemaElement;
  607. }
  608. if (elem == null)
  609. throw new InvalidOperationException ("Unknown array format");
  610. return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
  611. }
  612. }
  613. else
  614. {
  615. ClassMap cmap = new ClassMap ();
  616. CodeIdentifiers classIds = new CodeIdentifiers();
  617. ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);
  618. XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
  619. if (list != null && list.ChoiceMember == null)
  620. {
  621. arrayTypeData = list.TypeData;
  622. return list.ListMap;
  623. }
  624. else
  625. {
  626. arrayTypeData = null;
  627. return null;
  628. }
  629. }
  630. }
  631. ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
  632. {
  633. ListMap map = new ListMap ();
  634. int i = type.LastIndexOf ("[");
  635. if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
  636. if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
  637. string itemType = type.Substring (0,i);
  638. TypeData itemTypeData;
  639. if (itemType.IndexOf ("[") != -1)
  640. {
  641. ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
  642. int dims = itemType.Split ('[').Length - 1;
  643. string name = TypeTranslator.GetArrayName (type, dims);
  644. XmlQualifiedName qname = new XmlQualifiedName (name, ns);
  645. XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
  646. tmap.ObjectMap = innerListMap;
  647. }
  648. else
  649. {
  650. itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null);
  651. }
  652. arrayTypeData = itemTypeData.ListTypeData;
  653. map.ItemInfo = new XmlTypeMapElementInfoList();
  654. map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None));
  655. return map;
  656. }
  657. XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
  658. {
  659. foreach (object ob in atts)
  660. {
  661. XmlSchemaAttribute att = ob as XmlSchemaAttribute;
  662. if (att != null && att.RefName == arrayTypeRefName) return att;
  663. XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
  664. if (gref != null)
  665. {
  666. XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
  667. att = FindArrayAttribute (grp.Attributes);
  668. if (att != null) return att;
  669. }
  670. }
  671. return null;
  672. }
  673. void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
  674. {
  675. ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
  676. if (isMixed) AddTextMember (typeQName, cmap, classIds);
  677. }
  678. void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)
  679. {
  680. if (cmap.XmlTextCollector == null)
  681. {
  682. XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
  683. member.Name = classIds.AddUnique ("Text", member);
  684. member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
  685. member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
  686. member.IsXmlTextCollector = true;
  687. member.ListMap = new ListMap ();
  688. member.ListMap.ItemInfo = member.ElementInfo;
  689. cmap.AddMember (member);
  690. }
  691. }
  692. void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
  693. {
  694. if (particle == null) return;
  695. if (particle is XmlSchemaGroupRef)
  696. particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
  697. if (particle.MaxOccurs > 1) multiValue = true;
  698. if (particle is XmlSchemaSequence) {
  699. ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
  700. }
  701. else if (particle is XmlSchemaChoice) {
  702. if (((XmlSchemaChoice)particle).Items.Count == 1)
  703. ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
  704. else
  705. ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
  706. }
  707. else if (particle is XmlSchemaAll) {
  708. ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
  709. }
  710. }
  711. void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
  712. {
  713. foreach (XmlSchemaObject item in items)
  714. {
  715. if (item is XmlSchemaElement)
  716. {
  717. string ns;
  718. XmlSchemaElement elem = (XmlSchemaElement) item;
  719. XmlTypeMapping emap;
  720. TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
  721. XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
  722. if (elem.MaxOccurs == 1 && !multiValue)
  723. {
  724. XmlTypeMapMemberElement member = null;
  725. if (typeData.SchemaType != SchemaTypes.Array)
  726. {
  727. member = new XmlTypeMapMemberElement ();
  728. if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);
  729. }
  730. else if (GetTypeMapping (typeData).IsSimpleType)
  731. {
  732. // It is a simple list (space separated list).
  733. // Since this is not supported, map as a single item value
  734. // TODO: improve this
  735. member = new XmlTypeMapMemberElement ();
  736. typeData = typeData.ListItemTypeData;
  737. }
  738. else
  739. member = new XmlTypeMapMemberList ();
  740. if (elem.MinOccurs == 0 && typeData.IsValueType)
  741. member.IsOptionalValueType = true;
  742. member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
  743. member.Documentation = GetDocumentation (elem);
  744. member.TypeData = typeData;
  745. member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
  746. cmap.AddMember (member);
  747. }
  748. else
  749. {
  750. XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
  751. member.ListMap = new ListMap ();
  752. member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
  753. member.Documentation = GetDocumentation (elem);
  754. member.TypeData = typeData.ListTypeData;
  755. member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
  756. member.ListMap.ItemInfo = member.ElementInfo;
  757. cmap.AddMember (member);
  758. }
  759. }
  760. else if (item is XmlSchemaAny)
  761. {
  762. XmlSchemaAny elem = (XmlSchemaAny) item;
  763. XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
  764. member.Name = classIds.AddUnique ("Any", member);
  765. member.Documentation = GetDocumentation (elem);
  766. Type ctype;
  767. if (elem.MaxOccurs != 1 || multiValue)
  768. ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
  769. else
  770. ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
  771. member.TypeData = TypeTranslator.GetTypeData (ctype);
  772. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
  773. einfo.IsUnnamedAnyElement = true;
  774. member.ElementInfo.Add (einfo);
  775. if (isMixed)
  776. {
  777. einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
  778. member.ElementInfo.Add (einfo);
  779. member.IsXmlTextCollector = true;
  780. isMixed = false; //Allow only one XmlTextAttribute
  781. }
  782. cmap.AddMember (member);
  783. }
  784. else if (item is XmlSchemaParticle) {
  785. ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
  786. }
  787. }
  788. }
  789. object ImportDefaultValue (TypeData typeData, string value)
  790. {
  791. if (typeData.SchemaType == SchemaTypes.Enum) {
  792. XmlTypeMapping map = GetTypeMapping (typeData);
  793. EnumMap emap = (EnumMap) map.ObjectMap;
  794. string res = emap.GetEnumName (map.TypeFullName, value);
  795. if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
  796. return res;
  797. } else
  798. return XmlCustomFormatter.FromXmlString (typeData, value);
  799. }
  800. void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
  801. {
  802. XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
  803. multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
  804. if (choices.Count == 0) return;
  805. if (choice.MaxOccurs > 1) multiValue = true;
  806. XmlTypeMapMemberElement member;
  807. if (multiValue)
  808. {
  809. member = new XmlTypeMapMemberFlatList ();
  810. member.Name = classIds.AddUnique ("Items", member);
  811. ListMap listMap = new ListMap ();
  812. listMap.ItemInfo = choices;
  813. ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
  814. }
  815. else
  816. {
  817. member = new XmlTypeMapMemberElement ();
  818. member.Name = classIds.AddUnique ("Item", member);
  819. }
  820. // If all choices have the same type, use that type for the member.
  821. // If not use System.Object.
  822. // If there are at least two choices with the same type, use a choice
  823. // identifier attribute
  824. TypeData typeData = null;
  825. bool twoEqual = false;
  826. bool allEqual = true;
  827. Hashtable types = new Hashtable ();
  828. for (int n = choices.Count - 1; n >= 0; n--)
  829. {
  830. XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];
  831. // In some complex schemas, we may end up with several options
  832. // with the same name. It is better to ignore the extra options
  833. // than to crash. It's the best we can do, and btw it works
  834. // better than in MS.NET.
  835. if (cmap.GetElement (einfo.ElementName, einfo.Namespace) != null ||
  836. choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)
  837. {
  838. choices.RemoveAt (n);
  839. continue;
  840. }
  841. if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
  842. else types.Add (einfo.TypeData, einfo);
  843. TypeData choiceType = einfo.TypeData;
  844. if (choiceType.SchemaType == SchemaTypes.Class)
  845. {
  846. // When comparing class types, use the most generic class in the
  847. // inheritance hierarchy
  848. XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
  849. BuildPendingMap (choiceMap);
  850. while (choiceMap.BaseMap != null) {
  851. choiceMap = choiceMap.BaseMap;
  852. BuildPendingMap (choiceMap);
  853. choiceType = choiceMap.TypeData;
  854. }
  855. }
  856. if (typeData == null) typeData = choiceType;
  857. else if (typeData != choiceType) allEqual = false;
  858. }
  859. if (!allEqual)
  860. typeData = TypeTranslator.GetTypeData (typeof(object));
  861. if (twoEqual)
  862. {
  863. // Create the choice member
  864. XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
  865. choiceMember.Ignore = true;
  866. choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
  867. member.ChoiceMember = choiceMember.Name;
  868. // Create the choice enum
  869. XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
  870. enumMap.IncludeInSchema = false;
  871. CodeIdentifiers codeIdents = new CodeIdentifiers ();
  872. EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
  873. for (int n=0; n<choices.Count; n++)
  874. {
  875. XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
  876. bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);
  877. string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;
  878. string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
  879. members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
  880. }
  881. enumMap.ObjectMap = new EnumMap (members, false);
  882. choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
  883. choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None));
  884. cmap.AddMember (choiceMember);
  885. }
  886. if (multiValue)
  887. typeData = typeData.ListTypeData;
  888. member.ElementInfo = choices;
  889. member.Documentation = GetDocumentation (choice);
  890. member.TypeData = typeData;
  891. cmap.AddMember (member);
  892. }
  893. bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
  894. {
  895. bool multiValue = false;
  896. foreach (XmlSchemaObject titem in items)
  897. {
  898. XmlSchemaObject item = titem;
  899. if (item is XmlSchemaGroupRef)
  900. item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
  901. if (item is XmlSchemaElement)
  902. {
  903. string ns;
  904. XmlSchemaElement elem = (XmlSchemaElement) item;
  905. XmlTypeMapping emap;
  906. TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
  907. XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
  908. choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
  909. if (elem.MaxOccurs > 1) multiValue = true;
  910. }
  911. else if (item is XmlSchemaAny)
  912. {
  913. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
  914. einfo.IsUnnamedAnyElement = true;
  915. choices.Add (einfo);
  916. }
  917. else if (item is XmlSchemaChoice) {
  918. multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
  919. }
  920. else if (item is XmlSchemaSequence) {
  921. multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
  922. }
  923. }
  924. return multiValue;
  925. }
  926. void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
  927. {
  928. XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
  929. ClassMap cmap = (ClassMap)map.ObjectMap;
  930. XmlQualifiedName qname = GetContentBaseType (content.Content);
  931. TypeData simpleType = null;
  932. if (!IsPrimitiveTypeNamespace (qname.Namespace))
  933. {
  934. // Add base map members to this map
  935. XmlTypeMapping baseMap = ImportType (qname, null, true);
  936. BuildPendingMap (baseMap);
  937. if (baseMap.IsSimpleType) {
  938. simpleType = baseMap.TypeData;
  939. } else {
  940. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  941. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  942. cmap.AddMember (member);
  943. map.BaseMap = baseMap;
  944. baseMap.DerivedTypes.Add (map);
  945. }
  946. }
  947. else
  948. simpleType = FindBuiltInType (qname);
  949. if (simpleType != null) {
  950. XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
  951. member.Name = classIds.AddUnique("Value", member);
  952. member.TypeData = simpleType;
  953. member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
  954. member.IsXmlTextCollector = true;
  955. cmap.AddMember (member);
  956. }
  957. if (ext != null)
  958. ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
  959. }
  960. TypeData FindBuiltInType (XmlQualifiedName qname)
  961. {
  962. XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
  963. if (ct != null)
  964. {
  965. XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
  966. if (sc == null) throw new InvalidOperationException ("Invalid schema");
  967. return FindBuiltInType (GetContentBaseType (sc.Content));
  968. }
  969. XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
  970. if (st != null)
  971. return FindBuiltInType (qname, st);
  972. if (IsPrimitiveTypeNamespace (qname.Namespace))
  973. return TypeTranslator.GetPrimitiveTypeData (qname.Name);
  974. throw new InvalidOperationException ("Definition of type '" + qname + "' not found");
  975. }
  976. TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
  977. {
  978. if (CanBeEnum (st))
  979. return ImportType (qname, null, true).TypeData;
  980. if (st.Content is XmlSchemaSimpleTypeRestriction) {
  981. XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;
  982. XmlQualifiedName bn = GetContentBaseType (rest);
  983. if (bn == XmlQualifiedName.Empty && rest.BaseType != null)
  984. return FindBuiltInType (qname, rest.BaseType);
  985. else
  986. return FindBuiltInType (bn);
  987. }
  988. else if (st.Content is XmlSchemaSimpleTypeList) {
  989. return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
  990. }
  991. else if (st.Content is XmlSchemaSimpleTypeUnion)
  992. {
  993. // Check if all types of the union are equal. If not, then will use anyType.
  994. XmlSchemaSimpleTypeUnion uni = (XmlSchemaSimpleTypeUnion) st.Content;
  995. TypeData utype = null;
  996. // Anonymous types are unique
  997. if (uni.BaseTypes.Count != 0 && uni.MemberTypes.Length != 0)
  998. return FindBuiltInType (anyType);
  999. foreach (XmlQualifiedName mt in uni.MemberTypes)
  1000. {
  1001. TypeData qn = FindBuiltInType (mt);
  1002. if (utype != null && qn != utype) return FindBuiltInType (anyType);
  1003. else utype = qn;
  1004. }
  1005. return utype;
  1006. }
  1007. else
  1008. return null;
  1009. }
  1010. XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
  1011. {
  1012. if (ob is XmlSchemaSimpleContentExtension)
  1013. return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
  1014. else if (ob is XmlSchemaSimpleContentRestriction)
  1015. return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
  1016. else if (ob is XmlSchemaSimpleTypeRestriction)
  1017. return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
  1018. else if (ob is XmlSchemaSimpleTypeList)
  1019. return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
  1020. else
  1021. return null;
  1022. }
  1023. void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
  1024. {
  1025. ClassMap cmap = (ClassMap)map.ObjectMap;
  1026. XmlQualifiedName qname;
  1027. XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
  1028. if (ext != null) qname = ext.BaseTypeName;
  1029. else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
  1030. if (qname == typeQName)
  1031. throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");
  1032. // Add base map members to this map
  1033. XmlTypeMapping baseMap = ImportClass (qname);
  1034. BuildPendingMap (baseMap);
  1035. ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
  1036. foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
  1037. cmap.AddMember (member);
  1038. if (baseClassMap.XmlTextCollector != null) isMixed = false;
  1039. else if (content.IsMixed) isMixed = true;
  1040. map.BaseMap = baseMap;
  1041. baseMap.DerivedTypes.Add (map);
  1042. if (ext != null) {
  1043. // Add the members of this map
  1044. ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
  1045. ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
  1046. }
  1047. else {
  1048. if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
  1049. }
  1050. }
  1051. void ImportExtensionTypes (XmlQualifiedName qname)
  1052. {
  1053. foreach (XmlSchema schema in schemas) {
  1054. foreach (XmlSchemaObject sob in schema.Items)
  1055. {
  1056. XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
  1057. if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
  1058. XmlQualifiedName exqname;
  1059. XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
  1060. if (ext != null) exqname = ext.BaseTypeName;
  1061. else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
  1062. if (exqname == qname)
  1063. ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
  1064. }
  1065. }
  1066. }
  1067. }
  1068. XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
  1069. {
  1070. if (CanBeEnum (stype))
  1071. {
  1072. // Create an enum map
  1073. CodeIdentifiers codeIdents = new CodeIdentifiers ();
  1074. XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, null);
  1075. enumMap.Documentation = GetDocumentation (stype);
  1076. bool isFlags = false;
  1077. if (stype.Content is XmlSchemaSimpleTypeList) {
  1078. stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
  1079. isFlags = true;
  1080. }
  1081. XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
  1082. codeIdents.AddReserved (enumMap.TypeData.TypeName);
  1083. EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
  1084. for (int n=0; n<rest.Facets.Count; n++)
  1085. {
  1086. XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
  1087. string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
  1088. members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
  1089. members [n].Documentation = GetDocumentation (enu);
  1090. }
  1091. enumMap.ObjectMap = new EnumMap (members, isFlags);
  1092. enumMap.IsSimpleType = true;
  1093. return enumMap;
  1094. }
  1095. if (stype.Content is XmlSchemaSimpleTypeList)
  1096. {
  1097. XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
  1098. TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
  1099. ListMap listMap = new ListMap ();
  1100. listMap.ItemInfo = new XmlTypeMapElementInfoList ();
  1101. listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None));
  1102. XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
  1103. map.ObjectMap = listMap;
  1104. map.IsSimpleType = true;
  1105. return map;
  1106. }
  1107. // It is an extension of a primitive or known type
  1108. TypeData typeData = FindBuiltInType (typeQName, stype);
  1109. return GetTypeMapping (typeData);
  1110. }
  1111. bool CanBeEnum (XmlSchemaSimpleType stype)
  1112. {
  1113. if (stype.Content is XmlSchemaSimpleTypeRestriction)
  1114. {
  1115. XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
  1116. if (rest.Facets.Count == 0) return false;
  1117. foreach (object ob in rest.Facets)
  1118. if (!(ob is XmlSchemaEnumerationFacet)) return false;
  1119. return true;
  1120. }
  1121. else if (stype.Content is XmlSchemaSimpleTypeList)
  1122. {
  1123. XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;
  1124. return (list.ItemType != null && CanBeEnum (list.ItemType));
  1125. }
  1126. return false;
  1127. }
  1128. bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)
  1129. {
  1130. if (encodedFormat)
  1131. {
  1132. XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
  1133. if (content == null) return false;
  1134. XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
  1135. if (rest == null) return false;
  1136. return rest.BaseTypeName == arrayType;
  1137. }
  1138. else
  1139. {
  1140. if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;
  1141. else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);
  1142. }
  1143. }
  1144. bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)
  1145. {
  1146. // To be an array, there can't be a direct child of type typeQName
  1147. if (particle == null) return false;
  1148. multiValue = multiValue || particle.MaxOccurs > 1;
  1149. if (particle is XmlSchemaGroupRef)
  1150. return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);
  1151. if (particle is XmlSchemaElement)
  1152. {
  1153. XmlSchemaElement elem = (XmlSchemaElement)particle;
  1154. if (!elem.RefName.IsEmpty)
  1155. return CanBeArray (typeQName, FindRefElement (elem), multiValue);
  1156. else
  1157. return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);
  1158. }
  1159. if (particle is XmlSchemaAny)
  1160. return multiValue;
  1161. if (particle is XmlSchemaSequence)
  1162. {
  1163. XmlSchemaSequence seq = particle as XmlSchemaSequence;
  1164. if (seq.Items.Count != 1) return false;
  1165. return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);
  1166. }
  1167. if (particle is XmlSchemaChoice)
  1168. {
  1169. // Can be array if all choices have different types
  1170. ArrayList types = new ArrayList ();
  1171. if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;
  1172. return multiValue;
  1173. }
  1174. return false;
  1175. }
  1176. bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)
  1177. {
  1178. XmlQualifiedName type = null;
  1179. multiValue = multiValue || particle.MaxOccurs > 1;
  1180. if (particle is XmlSchemaGroupRef)
  1181. return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);
  1182. if (particle is XmlSchemaElement) {
  1183. string ns;
  1184. XmlSchemaElement elem = (XmlSchemaElement)particle;
  1185. XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
  1186. if (refElem.SchemaType != null) return true;
  1187. type = refElem.SchemaTypeName;
  1188. }
  1189. else if (particle is XmlSchemaAny) {
  1190. type = anyType;
  1191. }
  1192. else if (particle is XmlSchemaSequence)
  1193. {
  1194. XmlSchemaSequence seq = particle as XmlSchemaSequence;
  1195. foreach (XmlSchemaParticle par in seq.Items)
  1196. if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;
  1197. return true;
  1198. }
  1199. else if (particle is XmlSchemaChoice)
  1200. {
  1201. foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)
  1202. if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;
  1203. return true;
  1204. }
  1205. if (typeQName.Equals (type)) return false;
  1206. // For primitive types, compare using CLR types, since several
  1207. // xml types can be mapped to a single CLR type
  1208. string t;
  1209. if (IsPrimitiveTypeNamespace (type.Namespace))
  1210. t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;
  1211. else
  1212. t = type.Name + ":" + type.Namespace;
  1213. if (types.Contains (t)) return false;
  1214. types.Add (t);
  1215. return true;
  1216. }
  1217. bool CanBeAnyElement (XmlSchemaComplexType stype)
  1218. {
  1219. XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
  1220. return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);
  1221. }
  1222. Type GetAnyElementType (XmlSchemaComplexType stype)
  1223. {
  1224. XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
  1225. if ((seq == null) || (seq.Items.Count != 1) || !(seq.Items[0] is XmlSchemaAny))
  1226. return null;
  1227. if (encodedFormat)
  1228. return typeof(object);
  1229. XmlSchemaAny any = seq.Items[0] as XmlSchemaAny;
  1230. if (any.MaxOccurs == 1)
  1231. {
  1232. if (stype.IsMixed)
  1233. return typeof(XmlNode);
  1234. else
  1235. return typeof(XmlElement);
  1236. }
  1237. else
  1238. {
  1239. if (stype.IsMixed)
  1240. return typeof(XmlNode[]);
  1241. else
  1242. return typeof(XmlElement[]);
  1243. }
  1244. }
  1245. bool CanBeIXmlSerializable (XmlSchemaComplexType stype)
  1246. {
  1247. XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
  1248. if (seq == null) return false;
  1249. if (seq.Items.Count != 2) return false;
  1250. XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;
  1251. if (elem == null) return false;
  1252. if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;
  1253. return (seq.Items[1] is XmlSchemaAny);
  1254. }
  1255. XmlTypeMapping ImportXmlSerializableMapping (string ns)
  1256. {
  1257. XmlQualifiedName qname = new XmlQualifiedName ("System.Data.DataSet",ns);
  1258. XmlTypeMapping map = mappedTypes [qname] as XmlTypeMapping;
  1259. if (map != null) return map;
  1260. TypeData typeData = new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes.XmlSerializable, null);
  1261. map = new XmlTypeMapping ("System.Data.DataSet", "", typeData, "System.Data.DataSet", ns);
  1262. map.IncludeInSchema = true;
  1263. mappedTypes [qname] = map;
  1264. dataMappedTypes [typeData] = map;
  1265. return map;
  1266. }
  1267. XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form)
  1268. {
  1269. if (typeData.IsComplexType)
  1270. return CreateElementInfo (ns, member, name, typeData, isNillable, form, GetTypeMapping (typeData));
  1271. else
  1272. return CreateElementInfo (ns, member, name, typeData, isNillable, form, null);
  1273. }
  1274. XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, XmlTypeMapping emap)
  1275. {
  1276. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
  1277. einfo.ElementName = name;
  1278. einfo.Namespace = ns;
  1279. einfo.IsNullable = isNillable;
  1280. einfo.Form = form;
  1281. if (typeData.IsComplexType)
  1282. einfo.MappedType = emap;
  1283. return einfo;
  1284. }
  1285. XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)
  1286. {
  1287. XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
  1288. einfo.IsTextElement = true;
  1289. einfo.WrappedElement = false;
  1290. if (typeData.IsComplexType)
  1291. einfo.MappedType = GetTypeMapping (typeData);
  1292. return einfo;
  1293. }
  1294. XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)
  1295. {
  1296. string typeName = CodeIdentifier.MakeValid (typeQName.Name);
  1297. typeName = typeIdentifiers.AddUnique (typeName, null);
  1298. TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);
  1299. string rootElem;
  1300. string rootNs;
  1301. if (root != null) {
  1302. rootElem = root.Name;
  1303. rootNs = root.Namespace;
  1304. }
  1305. else {
  1306. rootElem = typeQName.Name;
  1307. rootNs = "";
  1308. }
  1309. XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);
  1310. map.IncludeInSchema = true;
  1311. mappedTypes [typeQName] = map;
  1312. dataMappedTypes [typeData] = map;
  1313. return map;
  1314. }
  1315. XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)
  1316. {
  1317. XmlTypeMapping map;
  1318. if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);
  1319. else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);
  1320. map.IncludeInSchema = true;
  1321. mappedTypes [typeQName] = map;
  1322. dataMappedTypes [arrayTypeData] = map;
  1323. return map;
  1324. }
  1325. XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)
  1326. {
  1327. if (!elem.RefName.IsEmpty)
  1328. {
  1329. ns = elem.RefName.Namespace;
  1330. return FindRefElement (elem);
  1331. }
  1332. else
  1333. {
  1334. ns = typeQName.Namespace;
  1335. return elem;
  1336. }
  1337. }
  1338. XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)
  1339. {
  1340. if (!attr.RefName.IsEmpty)
  1341. {
  1342. ns = attr.RefName.Namespace;
  1343. XmlSchemaAttribute at = FindRefAttribute (attr.RefName);
  1344. if (at == null) throw new InvalidOperationException ("The attribute " + attr.RefName + " is missing");
  1345. return at;
  1346. }
  1347. else
  1348. {
  1349. ns = typeQName.Namespace;
  1350. return attr;
  1351. }
  1352. }
  1353. TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem, XmlQualifiedName root, out XmlTypeMapping map)
  1354. {
  1355. bool sharedAnnType = false;
  1356. map = null;
  1357. if (!elem.RefName.IsEmpty) {
  1358. XmlSchemaElement refElem = FindRefElement (elem);
  1359. if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);
  1360. root = elem.RefName;
  1361. elem = refElem;
  1362. sharedAnnType = true;
  1363. }
  1364. TypeData td;
  1365. if (!elem.SchemaTypeName.IsEmpty) {
  1366. td = GetTypeData (elem.SchemaTypeName, root);
  1367. map = GetRegisteredTypeMapping (elem.SchemaTypeName);
  1368. }
  1369. else if (elem.SchemaType == null)
  1370. td = TypeTranslator.GetTypeData (typeof(object));
  1371. else
  1372. td = GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);
  1373. if (map == null && td.IsComplexType)
  1374. map = GetTypeMapping (td);
  1375. return td;
  1376. }
  1377. TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)
  1378. {
  1379. bool sharedAnnType = false;
  1380. if (!attr.RefName.IsEmpty) {
  1381. XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);
  1382. if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);
  1383. attr = refAtt;
  1384. sharedAnnType = true;
  1385. }
  1386. if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null);
  1387. if (attr.SchemaType == null) return TypeTranslator.GetTypeData (typeof(string));
  1388. else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);
  1389. }
  1390. TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root)
  1391. {
  1392. if (IsPrimitiveTypeNamespace (typeQName.Namespace)) {
  1393. XmlTypeMapping map = ImportType (typeQName, root, false);
  1394. if (map != null) return map.TypeData;
  1395. else return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
  1396. }
  1397. if (encodedFormat && typeQName.Namespace == "")
  1398. return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
  1399. return ImportType (typeQName, root, true).TypeData;
  1400. }
  1401. TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)
  1402. {
  1403. string baseName;
  1404. if (sharedAnnType)
  1405. {
  1406. // Anonymous types defined in root elements or attributes can be shared among all elements that
  1407. // reference this root element or attribute
  1408. TypeData std = sharedAnonymousTypes [stype] as TypeData;
  1409. if (std != null) return std;
  1410. baseName = propertyName;
  1411. }
  1412. else
  1413. baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);
  1414. baseName = elemIdentifiers.AddUnique (baseName, stype);
  1415. XmlQualifiedName newName;
  1416. newName = new XmlQualifiedName (baseName, typeQNname.Namespace);
  1417. XmlTypeMapping map = ImportType (newName, stype, root);
  1418. if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;
  1419. return map.TypeData;
  1420. }
  1421. XmlTypeMapping GetTypeMapping (TypeData typeData)
  1422. {
  1423. if (typeData.Type == typeof(object) && !anyTypeImported)
  1424. ImportAllObjectTypes ();
  1425. XmlTypeMapping map = (XmlTypeMapping) dataMappedTypes [typeData];
  1426. if (map != null) return map;
  1427. if (typeData.IsListType)
  1428. {
  1429. // Create an array map for the type
  1430. XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);
  1431. map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);
  1432. map.IncludeInSchema = true;
  1433. ListMap listMap = new ListMap ();
  1434. listMap.ItemInfo = new XmlTypeMapElementInfoList();
  1435. listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false, XmlSchemaForm.None));
  1436. map.ObjectMap = listMap;
  1437. mappedTypes [new XmlQualifiedName(map.ElementName, map.Namespace)] = map;
  1438. dataMappedTypes [typeData] = map;
  1439. return map;
  1440. }
  1441. else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))
  1442. {
  1443. return CreateSystemMap (typeData);
  1444. }
  1445. throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");
  1446. }
  1447. void AddObjectDerivedMap (XmlTypeMapping map)
  1448. {
  1449. TypeData typeData = TypeTranslator.GetTypeData (typeof(object));
  1450. XmlTypeMapping omap = (XmlTypeMapping) dataMappedTypes [typeData];
  1451. if (omap == null)
  1452. omap = CreateSystemMap (typeData);
  1453. omap.DerivedTypes.Add (map);
  1454. }
  1455. XmlTypeMapping CreateSystemMap (TypeData typeData)
  1456. {
  1457. XmlTypeMapping map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);
  1458. map.IncludeInSchema = false;
  1459. map.ObjectMap = new ClassMap ();
  1460. dataMappedTypes [typeData] = map;
  1461. return map;
  1462. }
  1463. void ImportAllObjectTypes ()
  1464. {
  1465. // All complex types are subtypes of anyType, so all of them
  1466. // must also be imported
  1467. anyTypeImported = true;
  1468. foreach (XmlSchema schema in schemas) {
  1469. foreach (XmlSchemaObject sob in schema.Items)
  1470. {
  1471. XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
  1472. if (sct != null)
  1473. ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
  1474. }
  1475. }
  1476. }
  1477. XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)
  1478. {
  1479. return (XmlTypeMapping) mappedTypes [typeQName];
  1480. }
  1481. XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)
  1482. {
  1483. XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));
  1484. return grp.Particle;
  1485. }
  1486. XmlSchemaElement FindRefElement (XmlSchemaElement elem)
  1487. {
  1488. XmlSchemaElement refelem = (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));
  1489. if (refelem != null) return refelem;
  1490. if (IsPrimitiveTypeNamespace (elem.RefName.Namespace))
  1491. {
  1492. if (anyElement != null) return anyElement;
  1493. anyElement = new XmlSchemaElement ();
  1494. anyElement.Name = "any";
  1495. anyElement.SchemaTypeName = anyType;
  1496. return anyElement;
  1497. } else
  1498. return null;
  1499. }
  1500. XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)
  1501. {
  1502. if (refName.Namespace == XmlNamespace)
  1503. {
  1504. XmlSchemaAttribute at = new XmlSchemaAttribute ();
  1505. at.Name = refName.Name;
  1506. at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
  1507. return at;
  1508. }
  1509. return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));
  1510. }
  1511. XmlSchemaAttributeGroup FindRefAttributeGroup (XmlQualifiedName refName)
  1512. {
  1513. XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (refName, typeof(XmlSchemaAttributeGroup));
  1514. foreach (XmlSchemaObject at in grp.Attributes)
  1515. {
  1516. if (at is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)at).RefName == refName)
  1517. throw new InvalidOperationException ("Cannot import attribute group '" + refName.Name + "' from namespace '" + refName.Namespace + "'. Redefine not supported");
  1518. }
  1519. return grp;
  1520. }
  1521. XmlTypeMapping ReflectType (Type type)
  1522. {
  1523. TypeData typeData = TypeTranslator.GetTypeData (type);
  1524. return ReflectType (typeData, (string) null);
  1525. }
  1526. XmlTypeMapping ReflectType (TypeData typeData, string ns)
  1527. {
  1528. if (!encodedFormat)
  1529. {
  1530. if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();
  1531. return auxXmlRefImporter.ImportTypeMapping (typeData, ns);
  1532. }
  1533. else
  1534. {
  1535. if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();
  1536. return auxSoapRefImporter.ImportTypeMapping (typeData, ns);
  1537. }
  1538. }
  1539. string GetDocumentation (XmlSchemaAnnotated elem)
  1540. {
  1541. string res = "";
  1542. XmlSchemaAnnotation anot = elem.Annotation;
  1543. if (anot == null || anot.Items == null) return null;
  1544. foreach (object ob in anot.Items)
  1545. {
  1546. XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;
  1547. if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {
  1548. if (res != string.Empty) res += "\n";
  1549. foreach (XmlNode node in doc.Markup)
  1550. res += node.Value;
  1551. }
  1552. }
  1553. return res;
  1554. }
  1555. bool IsPrimitiveTypeNamespace (string ns)
  1556. {
  1557. return (ns == XmlSchema.Namespace) || (encodedFormat && ns == XmlSerializer.EncodingNamespace);
  1558. }
  1559. #endregion // Methods
  1560. }
  1561. }