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);
81 dc_importer.Import (schema_set_in_use);
83 this.importer = importer;
84 this.context = context;
93 WsdlImporter importer;
94 WsdlContractConversionContext context;
96 XsdDataContractImporter dc_importer;
98 XmlSchemaSet schema_set_in_use;
100 void DoImportContract ()
102 PortType port_type = context.WsdlPortType;
103 ContractDescription contract = context.Contract;
105 List<MessagePartDescription> parts = new List<MessagePartDescription> ();
108 foreach (Operation op in port_type.Operations) {
109 OperationDescription opdescr = contract.Operations [i];
112 foreach (OperationMessage opmsg in op.Messages) {
113 //SM.MessageDescription
114 MessageDescription msgdescr = opdescr.Messages [j];
116 //OpMsg's corresponding WSMessage
117 Message msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
119 msgdescr.Body.WrapperNamespace = port_type.ServiceDescription.TargetNamespace;
121 if (opmsg is OperationOutput) {
123 msg = port_type.ServiceDescription.Messages [opmsg.Message.Name];
125 resolveMessage (msg, msgdescr.Body, parts);
126 if (parts.Count > 0) {
127 msgdescr.Body.ReturnValue = parts [0];
135 /* Parts, MessagePartDescription */
136 resolveMessage (msg, msgdescr.Body, parts);
137 foreach (MessagePartDescription p in parts)
138 msgdescr.Body.Parts.Add (p);
150 void resolveMessage (Message msg, MessageBodyDescription body, List<MessagePartDescription> parts)
152 foreach (MessagePart part in msg.Parts) {
153 if (part.Name == "parameters") {
154 if (!part.Element.IsEmpty) {
155 body.WrapperName = part.Element.Name;
156 ImportPartsBySchemaElement (part.Element, parts, body.WrapperNamespace);
158 body.WrapperName = part.Type.Name;
159 resolveType (part.Type, parts, body.WrapperNamespace);
162 //FIXME: non-parameters?
166 void ImportPartsBySchemaElement (QName qname, List<MessagePartDescription> parts, string ns)
168 XmlSchemaElement element = (XmlSchemaElement) schema_set_in_use.GlobalElements [qname];
170 //FIXME: What to do here?
171 throw new Exception ("Could not resolve : " + qname.ToString ());
173 var ct = element.ElementSchemaType as XmlSchemaComplexType;
174 if (ct == null) // simple type
175 parts.Add (CreateMessagePart (element));
177 foreach (var elem in GetElementsInParticle (ct.ContentTypeParticle))
178 parts.Add (CreateMessagePart (elem));
181 IEnumerable<XmlSchemaElement> GetElementsInParticle (XmlSchemaParticle p)
183 if (p is XmlSchemaElement) {
184 yield return (XmlSchemaElement) p;
186 var gb = p as XmlSchemaGroupBase;
188 foreach (XmlSchemaParticle pp in gb.Items)
189 foreach (var e in GetElementsInParticle (pp))
194 MessagePartDescription CreateMessagePart (XmlSchemaElement elem)
196 var part = new MessagePartDescription (elem.QualifiedName.Name, elem.QualifiedName.Namespace);
197 part.Importer = dc_importer;
198 var typeQName = dc_importer.Import (schema_set_in_use, elem);
199 part.CodeTypeReference = dc_importer.GetCodeTypeReference (typeQName);
203 void resolveType (QName qname, List<MessagePartDescription> parts, string ns)
205 /*foreach (XmlSchema xs in importer.Schemas)
206 if (xs.Types [qname] != null)
207 return resolveParameters ((XmlSchemaElement) xs.Types [qname]., msgdescr, importer);
209 //FIXME: What to do here?
210 throw new Exception ("Could not resolve : " + qname.ToString ());*/
211 throw new NotImplementedException ();
214 internal static string GetCLRTypeName (QName qname)
216 switch (qname.Namespace) {
217 case "http://schemas.microsoft.com/2003/10/Serialization/":
218 if (qname.Name == "duration")
219 return "System.TimeSpan";
220 if (qname.Name == "guid")
221 return "System.Guid";
223 case "http://www.w3.org/2001/XMLSchema":
224 return GetCLRTypeName (qname.Name);
229 internal static string GetCLRTypeName (string xsdName)
233 return "System.String";
235 return "System.Boolean";
237 //FIXME: case "base64Binary":
239 return "System.DateTime";
241 return "System.String";
243 return "System.Decimal";
245 return "System.Double";
247 return "System.Double";
249 return "System.SByte";
251 return "System.Int16";
253 return "System.Int32";
255 return "System.Int64";
257 return "System.Byte";
258 case "unsignedShort":
259 return "System.UInt16";
261 return "System.UInt32";
263 return "System.UInt64";
265 return "System.String";
276 void IWsdlImportExtension.ImportEndpoint (WsdlImporter importer,
277 WsdlEndpointConversionContext context)