2 // DataContractSerializerMessageContractImporter.cs
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
5 // Ankit Jain (jankit@novell.com)
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.Collections.ObjectModel;
31 using System.ServiceModel;
33 using System.Web.Services.Description;
35 using System.Xml.Schema;
36 using System.Xml.Serialization;
38 using QName = System.Xml.XmlQualifiedName;
39 using WSDL = System.Web.Services.Description.ServiceDescription;
41 namespace System.ServiceModel.Description
44 public class DataContractSerializerMessageContractImporter
45 : IWsdlImportExtension
50 get { return enabled; }
51 set { enabled = value; }
54 void IWsdlImportExtension.BeforeImport (
55 ServiceDescriptionCollection wsdlDocuments,
56 XmlSchemaSet xmlSchemas,
57 ICollection<XmlElement> policy)
61 void IWsdlImportExtension.ImportContract (WsdlImporter importer,
62 WsdlContractConversionContext context)
68 throw new ArgumentNullException ("importer");
70 throw new ArgumentNullException ("context");
71 if (this.importer != null || this.context != null)
72 throw new SystemException ("INTERNAL ERROR: unexpected recursion of ImportContract method call");
74 this.importer = importer;
75 this.context = context;
84 WsdlImporter importer;
85 WsdlContractConversionContext context;
86 XmlSchemaImporter schema_importer_;
87 XmlSchemaImporter schema_importer {
89 if (schema_importer_ != null)
90 return schema_importer_;
91 schema_importer_ = new XmlSchemaImporter (xml_schemas);
92 return schema_importer_;
96 XmlSchemas xml_schemas_;
97 XmlSchemas xml_schemas {
99 if (xml_schemas_ != null)
101 xml_schemas_ = new XmlSchemas ();
103 foreach (WSDL wsdl in importer.WsdlDocuments)
104 foreach (XmlSchema schema in wsdl.Types.Schemas)
105 xml_schemas_.Add (schema);
107 foreach (XmlSchema schema in importer.XmlSchemas.Schemas ())
108 xml_schemas_.Add (schema);
110 xml_schemas_.Compile (null, true);
116 void DoImportContract ()
118 PortType port_type = context.WsdlPortType;
119 ContractDescription contract = context.Contract;
121 List<MessagePartDescription> parts = new List<MessagePartDescription> ();
124 foreach (Operation op in port_type.Operations) {
125 OperationDescription opdescr = contract.Operations [i];
128 foreach (OperationMessage opmsg in op.Messages) {
129 //SM.MessageDescription
130 MessageDescription msgdescr = opdescr.Messages [j];
132 //OpMsg's corresponding WSMessage
133 Message msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
135 msgdescr.Body.WrapperNamespace = port_type.ServiceDescription.TargetNamespace;
137 if (opmsg is OperationOutput) {
139 msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
141 resolveMessage (msg, msgdescr.Body, parts);
142 if (parts.Count > 0) {
143 msgdescr.Body.ReturnValue = parts [0];
151 /* Parts, MessagePartDescription */
152 resolveMessage (msg, msgdescr.Body, parts);
153 foreach (MessagePartDescription p in parts)
154 msgdescr.Body.Parts.Add (p);
166 void resolveMessage (Message msg, MessageBodyDescription body, List<MessagePartDescription> parts)
168 foreach (MessagePart part in msg.Parts) {
169 if (part.Name == "parameters") {
170 if (!part.Element.IsEmpty) {
171 body.WrapperName = part.Element.Name;
172 resolveElement (part.Element, parts, body.WrapperNamespace);
174 body.WrapperName = part.Type.Name;
175 resolveType (part.Type, parts, body.WrapperNamespace);
178 //FIXME: non-parameters?
182 void resolveElement (QName qname, List<MessagePartDescription> parts, string ns)
184 XmlSchemaElement element = (XmlSchemaElement) xml_schemas.Find (qname, typeof (XmlSchemaElement));
186 //FIXME: What to do here?
187 throw new Exception ("Could not resolve : " + qname.ToString ());
189 resolveParticle (schema_importer, element, parts, ns, 2);
192 void resolveType (QName qname, List<MessagePartDescription> parts, string ns)
194 /*foreach (XmlSchema xs in importer.Schemas)
195 if (xs.Types [qname] != null)
196 return resolveParameters ((XmlSchemaElement) xs.Types [qname]., msgdescr, importer);
198 //FIXME: What to do here?
199 throw new Exception ("Could not resolve : " + qname.ToString ());*/
200 throw new NotImplementedException ();
203 string GetCLRTypeName (QName qname)
205 if (qname.Namespace != "http://www.w3.org/2001/XMLSchema")
208 switch (qname.Name) {
210 return "System.String";
212 return "System.Boolean";
214 /*FIXME: case "base64Binary":
218 return "System.String";
220 return "System.Decimal";
222 return "System.Double";
224 return "System.Double";
226 return "System.SByte";
228 return "System.Int16";
230 return "System.Int32";
232 return "System.Int64";
234 return "System.Byte";
235 case "unsignedShort":
236 return "System.UInt16";
238 return "System.UInt32";
240 return "System.UInt64";
242 return "System.String";
253 void resolveParticle (XmlSchemaImporter schema_importer,
254 XmlSchemaParticle particle,
255 List<MessagePartDescription> parts,
259 if (particle is XmlSchemaGroupBase) {
265 XmlSchemaGroupBase groupBase = particle as XmlSchemaGroupBase;
266 foreach (XmlSchemaParticle item in groupBase.Items)
267 resolveParticle (schema_importer, item, parts, ns, depth - 1);
272 XmlSchemaElement elem = particle as XmlSchemaElement;
276 MessagePartDescription msg_part = null;
278 XmlSchemaComplexType ct = elem.ElementSchemaType as XmlSchemaComplexType;
281 XmlSchemaSimpleType simple = elem.ElementSchemaType as XmlSchemaSimpleType;
282 msg_part = new MessagePartDescription (
284 if (elem.SchemaType != null)
285 msg_part.XmlTypeMapping = schema_importer.ImportTypeMapping (elem.QualifiedName);
287 msg_part.XmlTypeMapping = schema_importer.ImportSchemaType (elem.SchemaTypeName);
288 msg_part.TypeName = new QName (GetCLRTypeName (elem.SchemaTypeName), "");
289 parts.Add (msg_part);
295 resolveParticle (schema_importer, ct.ContentTypeParticle, parts, ns, depth - 1);
300 msg_part = new MessagePartDescription (elem.Name, ns);
301 if (elem.SchemaType != null)
302 msg_part.XmlTypeMapping = schema_importer.ImportTypeMapping (elem.QualifiedName);
304 msg_part.XmlTypeMapping = schema_importer.ImportSchemaType (elem.SchemaTypeName);
305 msg_part.TypeName = elem.SchemaTypeName;
307 parts.Add (msg_part);
310 void IWsdlImportExtension.ImportEndpoint (WsdlImporter importer,
311 WsdlEndpointConversionContext context)