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.Runtime.Serialization;
32 using System.ServiceModel;
34 using System.Web.Services.Description;
36 using System.Xml.Schema;
37 using System.Xml.Serialization;
39 using QName = System.Xml.XmlQualifiedName;
40 using WSDL = System.Web.Services.Description.ServiceDescription;
42 namespace System.ServiceModel.Description
45 public class DataContractSerializerMessageContractImporter
46 : IWsdlImportExtension
51 get { return enabled; }
52 set { enabled = value; }
55 void IWsdlImportExtension.BeforeImport (
56 ServiceDescriptionCollection wsdlDocuments,
57 XmlSchemaSet xmlSchemas,
58 ICollection<XmlElement> policy)
62 void IWsdlImportExtension.ImportContract (WsdlImporter importer,
63 WsdlContractConversionContext context)
69 throw new ArgumentNullException ("importer");
71 throw new ArgumentNullException ("context");
72 if (this.importer != null || this.context != null)
73 throw new SystemException ("INTERNAL ERROR: unexpected recursion of ImportContract method call");
75 dc_importer = new XsdDataContractImporter ();
76 schema_set_in_use = new XmlSchemaSet ();
77 schema_set_in_use.Add (importer.XmlSchemas);
78 foreach (WSDL wsdl in importer.WsdlDocuments)
79 foreach (XmlSchema xs in wsdl.Types.Schemas)
80 schema_set_in_use.Add (xs);
82 // commenting out this import operation, but might be required (I guess not).
83 //dc_importer.Import (schema_set_in_use);
84 schema_set_in_use.Compile ();
86 this.importer = importer;
87 this.context = context;
96 WsdlImporter importer;
97 WsdlContractConversionContext context;
99 XsdDataContractImporter dc_importer;
101 XmlSchemaSet schema_set_in_use;
103 void DoImportContract ()
105 PortType port_type = context.WsdlPortType;
106 ContractDescription contract = context.Contract;
108 List<MessagePartDescription> parts = new List<MessagePartDescription> ();
111 foreach (Operation op in port_type.Operations) {
112 OperationDescription opdescr = contract.Operations [i];
115 foreach (OperationMessage opmsg in op.Messages) {
116 //SM.MessageDescription
117 MessageDescription msgdescr = opdescr.Messages [j];
119 //OpMsg's corresponding WSMessage
120 Message msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
122 msgdescr.Body.WrapperNamespace = port_type.ServiceDescription.TargetNamespace;
124 if (opmsg is OperationOutput) {
126 msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
128 resolveMessage (msg, msgdescr.Body, parts);
129 if (parts.Count > 0) {
130 msgdescr.Body.ReturnValue = parts [0];
138 /* Parts, MessagePartDescription */
139 resolveMessage (msg, msgdescr.Body, parts);
140 foreach (MessagePartDescription p in parts)
141 msgdescr.Body.Parts.Add (p);
153 void resolveMessage (Message msg, MessageBodyDescription body, List<MessagePartDescription> parts)
155 foreach (MessagePart part in msg.Parts) {
156 if (part.Name == "parameters") {
157 if (!part.Element.IsEmpty) {
158 body.WrapperName = part.Element.Name;
159 ImportPartsBySchemaElement (part.Element, parts, body.WrapperNamespace);
161 body.WrapperName = part.Type.Name;
162 resolveType (part.Type, parts, body.WrapperNamespace);
165 //FIXME: non-parameters?
169 void ImportPartsBySchemaElement (QName qname, List<MessagePartDescription> parts, string ns)
171 XmlSchemaElement element = (XmlSchemaElement) schema_set_in_use.GlobalElements [qname];
173 //FIXME: What to do here?
174 throw new Exception ("Could not resolve : " + qname.ToString ());
176 var ct = element.ElementSchemaType as XmlSchemaComplexType;
177 if (ct == null) // simple type
178 parts.Add (CreateMessagePart (element));
180 foreach (var elem in GetElementsInParticle (ct.ContentTypeParticle))
181 parts.Add (CreateMessagePart (elem));
184 IEnumerable<XmlSchemaElement> GetElementsInParticle (XmlSchemaParticle p)
186 if (p is XmlSchemaElement) {
187 yield return (XmlSchemaElement) p;
189 var gb = p as XmlSchemaGroupBase;
191 foreach (XmlSchemaParticle pp in gb.Items)
192 foreach (var e in GetElementsInParticle (pp))
197 MessagePartDescription CreateMessagePart (XmlSchemaElement elem)
199 var part = new MessagePartDescription (elem.QualifiedName.Name, elem.QualifiedName.Namespace);
200 part.Importer = dc_importer;
201 var typeQName = dc_importer.Import (schema_set_in_use, elem);
202 part.CodeTypeReference = dc_importer.GetCodeTypeReference (typeQName);
206 void resolveType (QName qname, List<MessagePartDescription> parts, string ns)
208 /*foreach (XmlSchema xs in importer.Schemas)
209 if (xs.Types [qname] != null)
210 return resolveParameters ((XmlSchemaElement) xs.Types [qname]., msgdescr, importer);
212 //FIXME: What to do here?
213 throw new Exception ("Could not resolve : " + qname.ToString ());*/
214 throw new NotImplementedException ();
217 internal static string GetCLRTypeName (QName qname)
219 switch (qname.Namespace) {
220 case "http://schemas.microsoft.com/2003/10/Serialization/":
221 if (qname.Name == "duration")
222 return "System.TimeSpan";
223 if (qname.Name == "guid")
224 return "System.Guid";
226 case "http://www.w3.org/2001/XMLSchema":
227 return GetCLRTypeName (qname.Name);
232 internal static string GetCLRTypeName (string xsdName)
236 return "System.String";
238 return "System.Boolean";
240 //FIXME: case "base64Binary":
242 return "System.DateTime";
244 return "System.String";
246 return "System.Decimal";
248 return "System.Double";
250 return "System.Double";
252 return "System.SByte";
254 return "System.Int16";
256 return "System.Int32";
258 return "System.Int64";
260 return "System.Byte";
261 case "unsignedShort":
262 return "System.UInt16";
264 return "System.UInt32";
266 return "System.UInt64";
268 return "System.String";
279 void IWsdlImportExtension.ImportEndpoint (WsdlImporter importer,
280 WsdlEndpointConversionContext context)