ongoing Sys.SM.Discovery serialization implementation.
[mono.git] / mcs / class / System.ServiceModel.Discovery / System.ServiceModel.Discovery / FindCriteria.cs
1 //
2 // Author: Atsushi Enomoto <atsushi@ximian.com>
3 //
4 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 // 
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 // 
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25 using System;
26 using System.Collections.Generic;
27 using System.Collections.ObjectModel;
28 using System.ServiceModel;
29 using System.ServiceModel.Channels;
30 using System.ServiceModel.Description;
31 using System.ServiceModel.Dispatcher;
32 using System.Xml;
33 using System.Xml.Schema;
34 using System.Xml.Linq;
35
36 namespace System.ServiceModel.Discovery
37 {
38         public class FindCriteria
39         {
40                 const string SerializationNS = "http://schemas.microsoft.com/ws/2008/06/discovery";
41                 const int default_max_results = int.MaxValue;
42
43                 public static readonly Uri ScopeMatchByExact = new Uri ("http://schemas.microsoft.com/ws/2008/06/discovery/strcmp0");
44                 public static readonly Uri ScopeMatchByLdap = new Uri ("http://schemas.microsoft.com/ws/2008/06/discovery/ldap");
45                 public static readonly Uri ScopeMatchByNone = new Uri ("http://schemas.microsoft.com/ws/2008/06/discovery/none");
46                 public static readonly Uri ScopeMatchByPrefix = new Uri ("http://schemas.microsoft.com/ws/2008/06/discovery/rfc3986");
47                 public static readonly Uri ScopeMatchByUuid = new Uri ("http://schemas.microsoft.com/ws/2008/06/discovery/uuid");
48
49                 public static FindCriteria CreateMetadataExchangeEndpointCriteria ()
50                 {
51                         return CreateMetadataExchangeEndpointCriteria (typeof (IMetadataExchange));
52                 }
53
54                 public static FindCriteria CreateMetadataExchangeEndpointCriteria (IEnumerable<XmlQualifiedName> contractTypeNames)
55                 {
56                         var fc = new FindCriteria ();
57                         foreach (var type in contractTypeNames)
58                                 fc.ContractTypeNames.Add (type);
59                         return fc;
60                 }
61
62                 public static FindCriteria CreateMetadataExchangeEndpointCriteria (Type contractType)
63                 {
64                         return new FindCriteria (contractType);
65                 }
66
67                 public FindCriteria ()
68                 {
69                         ContractTypeNames = new Collection<XmlQualifiedName> ();
70                         Extensions = new Collection<XElement> ();
71                         Scopes = new Collection<Uri> ();
72                         MaxResults = default_max_results;
73                 }
74
75                 public FindCriteria (Type contractType)
76                         : this ()
77                 {
78                         var cd = ContractDescription.GetContract (contractType);
79                         ContractTypeNames.Add (new XmlQualifiedName (cd.Name, cd.Namespace));
80                 }
81
82                 public Collection<XmlQualifiedName> ContractTypeNames { get; private set; }
83                 public TimeSpan Duration { get; set; }
84                 public Collection<XElement> Extensions { get; private set; }
85                 public int MaxResults { get; set; }
86                 public Uri ScopeMatchBy { get; set; }
87                 public Collection<Uri> Scopes { get; private set; }
88
89                 [MonoTODO]
90                 public bool IsMatch (EndpointDiscoveryMetadata endpointDiscoveryMetadata)
91                 {
92                         throw new NotImplementedException ();
93                 }
94
95                 internal static FindCriteria ReadXml (XmlReader reader, DiscoveryVersion version)
96                 {
97                         if (reader == null)
98                                 throw new ArgumentNullException ("reader");
99
100                         var ret = new FindCriteria ();
101
102                         reader.MoveToContent ();
103                         if (!reader.IsStartElement ("ProbeType", version.Namespace) || reader.IsEmptyElement)
104                                 throw new XmlException ("Non-empty ProbeType element is expected");
105                         reader.ReadStartElement ("ProbeType", version.Namespace);
106
107                         // standard members
108                         reader.MoveToContent ();
109                         bool isEmpty = reader.IsEmptyElement;
110                         ret.ContractTypeNames = new Collection<XmlQualifiedName> ((XmlQualifiedName []) reader.ReadElementContentAs (typeof (XmlQualifiedName []), null, "Types", version.Namespace));
111
112                         reader.MoveToContent ();
113                         if (!reader.IsStartElement ("Scopes", version.Namespace))
114                                 throw new XmlException ("Scopes element is expected");
115                         if (reader.MoveToAttribute ("MatchBy")) {
116                                 ret.ScopeMatchBy = new Uri (reader.Value, UriKind.RelativeOrAbsolute);
117                                 reader.MoveToElement ();
118                         }
119                         ret.Scopes = new Collection<Uri> ((Uri []) reader.ReadElementContentAs (typeof (Uri []), null, "Scopes", version.Namespace));
120
121                         // non-standard members
122                         for (reader.MoveToContent (); !reader.EOF && reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
123                                 if (reader.NamespaceURI == SerializationNS) {
124                                         switch (reader.LocalName) {
125                                         case "MaxResults":
126                                                 ret.MaxResults = reader.ReadElementContentAsInt ();
127                                                 break;
128                                         case "Duration":
129                                                 ret.Duration = (TimeSpan) reader.ReadElementContentAs (typeof (TimeSpan), null);
130                                                 break;
131                                         }
132                                 }
133                                 else
134                                         ret.Extensions.Add (XElement.Load (reader));
135                         }
136
137                         reader.ReadEndElement ();
138
139                         return ret;
140                 }
141
142                 internal void WriteXml (XmlWriter writer, DiscoveryVersion version)
143                 {
144                         if (writer == null)
145                                 throw new ArgumentNullException ("writer");
146
147                         writer.WriteStartElement ("ProbeType", version.Namespace);
148
149                         // standard members
150                         writer.WriteStartElement ("d", "Types", version.Namespace);
151                         int p = 0;
152                         foreach (var qname in ContractTypeNames)
153                                 if (writer.LookupPrefix (qname.Namespace) == null)
154                                         writer.WriteAttributeString ("xmlns", "p" + p++, "http://www.w3.org/2000/xmlns/", qname.Namespace);
155                         writer.WriteValue (ContractTypeNames);
156                         writer.WriteEndElement ();
157
158                         writer.WriteStartElement ("Scopes", version.Namespace);
159                         if (ScopeMatchBy != null) {
160                                 writer.WriteStartAttribute ("MatchBy");
161                                 writer.WriteValue (ScopeMatchBy);
162                                 writer.WriteEndAttribute ();
163                         }
164                         writer.WriteValue (Scopes);
165                         writer.WriteEndElement ();
166
167                         // non-standard members
168                         if (MaxResults != default_max_results) {
169                                 writer.WriteStartElement ("MaxResults", SerializationNS);
170                                 writer.WriteValue (MaxResults);
171                                 writer.WriteEndElement ();
172                         }
173                         writer.WriteStartElement ("Duration", SerializationNS);
174                         writer.WriteValue (Duration);
175                         writer.WriteEndElement ();
176                         
177                         foreach (var ext in Extensions)
178                                 ext.WriteTo (writer);
179
180                         writer.WriteEndElement ();
181                 }
182
183                 internal static XmlSchema BuildSchema (DiscoveryVersion version)
184                 {
185                         var schema = new XmlSchema () { TargetNamespace = version.Namespace };
186
187                         var anyAttr = new XmlSchemaAnyAttribute () { Namespace = "##other", ProcessContents = XmlSchemaContentProcessing.Lax };
188
189                         var probePart = new XmlSchemaSequence ();
190                         probePart.Items.Add (new XmlSchemaElement () { RefName = new XmlQualifiedName ("Types", version.Namespace), MinOccurs = 0 });
191                         probePart.Items.Add (new XmlSchemaElement () { RefName = new XmlQualifiedName ("Scopes", version.Namespace), MinOccurs = 0 });
192                         probePart.Items.Add (new XmlSchemaAny () { MinOccurs = 0, MaxOccursString = "unbounded", Namespace = "##other", ProcessContents = XmlSchemaContentProcessing.Lax });
193                         var ct = new XmlSchemaComplexType () { Name = "ProbeType", Particle = probePart, AnyAttribute = anyAttr };
194                         schema.Items.Add (ct);
195
196                         schema.Items.Add (new XmlSchemaSimpleType () { Name = "QNameListType", Content = new XmlSchemaSimpleTypeList () { ItemTypeName = new XmlQualifiedName ("QName", XmlSchema.Namespace) } });
197
198                         var scr = new XmlSchemaSimpleContentRestriction () { BaseTypeName = new XmlQualifiedName ("UriListType", version.Namespace), AnyAttribute = anyAttr };
199                         scr.Attributes.Add (new XmlSchemaAttribute () { Name = "matchBy", SchemaTypeName = new XmlQualifiedName ("anyURI", XmlSchema.Namespace) });
200                         schema.Items.Add (new XmlSchemaComplexType () { Name = "ScopesType", ContentModel = new XmlSchemaSimpleContent () { Content = scr } });
201
202                         schema.Items.Add (new XmlSchemaSimpleType () { Name = "UriListType", Content = new XmlSchemaSimpleTypeList () { ItemTypeName = new XmlQualifiedName ("anyURI", XmlSchema.Namespace) } });
203
204                         schema.Items.Add (new XmlSchemaElement () { Name = "Types", SchemaTypeName = new XmlQualifiedName ("QNameListType", version.Namespace) });
205                         schema.Items.Add (new XmlSchemaElement () { Name = "Scopes", SchemaTypeName = new XmlQualifiedName ("ScopesType", version.Namespace) });
206
207                         return schema;
208                 }
209         }
210 }