Author: atsushi
Date: 2008-02-12 13:22:50 -0500 (Tue, 12 Feb 2008)
New Revision: 95540
Modified:
trunk/olive/class/System.ServiceModel.Web/System/ChangeLog
trunk/olive/class/System.ServiceModel.Web/System/UriTemplate.cs
trunk/olive/class/System.ServiceModel.Web/System/UriTemplateMatch.cs
trunk/olive/class/System.ServiceModel.Web/System/UriTemplateTable.cs
trunk/olive/class/System.ServiceModel.Web/Test/System/ChangeLog
trunk/olive/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs
Log:
2008-02-12 Atsushi Enomoto <[EMAIL PROTECTED]>
* UriTemplateMatch.cs : implemented some members.
* UriTemplateTable.cs : implemented Match() and MatchSingle().
* UriTemplate.cs : Do not expand template in non-path-query area.
Implemented Match().
* UriTemplateTest.cs : Added tests for Match() and more Binding tests.
Modified: trunk/olive/class/System.ServiceModel.Web/System/ChangeLog
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/System/ChangeLog 2008-02-12
18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/System/ChangeLog 2008-02-12
18:22:50 UTC (rev 95540)
@@ -1,5 +1,12 @@
2008-02-12 Atsushi Enomoto <[EMAIL PROTECTED]>
+ * UriTemplateMatch.cs : implemented some members.
+ * UriTemplateTable.cs : implemented Match() and MatchSingle().
+ * UriTemplate.cs : Do not expand template in non-path-query area.
+ Implemented Match().
+
+2008-02-12 Atsushi Enomoto <[EMAIL PROTECTED]>
+
* UriTemplateTable.cs, UriTemplateEquivalenceComparer.cs : new stubs.
* UriTemplateMatchException.cs : new.
* UriTemplate.cs : implemented .ctor(), BindByName() and
Modified: trunk/olive/class/System.ServiceModel.Web/System/UriTemplate.cs
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/System/UriTemplate.cs
2008-02-12 18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/System/UriTemplate.cs
2008-02-12 18:22:50 UTC (rev 95540)
@@ -39,19 +39,26 @@
static readonly ReadOnlyCollection<string> empty_strings = new
ReadOnlyCollection<string> (new string [0]);
string template;
- Uri uri;
ReadOnlyCollection<string> path, query;
+ [MonoTODO ("It needs some rewrite: template bindings should be
available only one per segment")]
public UriTemplate (string template)
{
if (template == null)
throw new ArgumentNullException ("template");
this.template = template;
- int q = template.IndexOf ('?');
- path = ParseTemplate (template, 0, q >= 0 ? q :
template.Length);
+ string p = template;
+ // Trim scheme, host name and port if exist.
+ if (CultureInfo.InvariantCulture.CompareInfo.IsPrefix
(template, "http")) {
+ int idx = template.IndexOf ('/', 8); // after
"http://x" or "https://"
+ if (idx > 0)
+ p = template.Substring (idx);
+ }
+ int q = p.IndexOf ('?');
+ path = ParseTemplate (p, 0, q >= 0 ? q : p.Length);
if (q >= 0)
- query = ParseTemplate (template, q,
template.Length);
+ query = ParseTemplate (p, q, p.Length);
else
query = empty_strings;
}
@@ -64,6 +71,13 @@
get { return query; }
}
+ public override string ToString ()
+ {
+ return template;
+ }
+
+ // Bind
+
public Uri BindByName (Uri baseAddress, NameValueCollection
parameters)
{
CheckBaseAddress (baseAddress);
@@ -107,7 +121,7 @@
void BindByPosition (ref int src, StringBuilder sb,
ReadOnlyCollection<string> names, string [] values, ref int index)
{
- foreach (string name in names) {
+ for (int i = 0; i < names.Count; i++) {
int s = template.IndexOf ('{', src);
int e = template.IndexOf ('}', s + 1);
sb.Append (template.Substring (src, s - src));
@@ -119,29 +133,80 @@
}
}
+ // Compare
+
[MonoTODO]
public bool IsEquivalentTo (UriTemplate other)
{
- throw new NotImplementedException ();
+ if (other == null)
+ throw new ArgumentNullException ("other");
+ return new UriTemplateEquivalenceComparer ().Equals
(this, other);
}
- [MonoTODO]
+ // Match
+
public UriTemplateMatch Match (Uri baseAddress, Uri candidate)
{
- throw new NotImplementedException ();
+ CheckBaseAddress (baseAddress);
+ if (candidate == null)
+ throw new ArgumentNullException ("candidate");
+
+ if (Uri.Compare (baseAddress, candidate,
UriComponents.StrongAuthority, UriFormat.SafeUnescaped,
StringComparison.Ordinal) != 0)
+ return null;
+
+ int i = 0, c = 0;
+ UriTemplateMatch m = new UriTemplateMatch ();
+ m.BaseUri = baseAddress;
+ m.Template = this;
+ var vc = m.BoundVariables;
+
+ string cp = candidate.PathAndQuery;
+ foreach (string name in path) {
+ int n = StringIndexOf (template, '{' + name +
'}', i);
+ if (String.CompareOrdinal (cp, c, template, i,
n - i) != 0)
+ return null; // doesn't match before
current template part.
+ c += n - i;
+ i = n + 2 + name.Length;
+ int ce = cp.IndexOf ('/', c);
+ if (ce < 0)
+ ce = cp.Length;
+ string value = cp.Substring (c, ce - c);
+ vc [name] = value;
+ c += value.Length;
+ }
+ foreach (string name in query) {
+ int n = StringIndexOf (template, '{' + name +
'}', i);
+ if (String.CompareOrdinal (cp, c, template, i,
n - i) != 0)
+ return null; // doesn't match before
current template part.
+ c += n - i;
+ i = n + 2 + name.Length;
+ int ce = cp.IndexOf ('&', c);
+ if (ce < 0)
+ ce = cp.Length;
+ string value = cp.Substring (c, ce - c);
+ vc [name] = value;
+ c += value.Length;
+ }
+ if ((cp.Length - c) != (template.Length - i) ||
+ String.CompareOrdinal (cp, c, template, i,
template.Length - i) != 0)
+ return null; // suffix doesn't match
+
+ return m;
}
- public override string ToString ()
+ int StringIndexOf (string s, string pattern, int idx)
{
- return template;
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf
(s, pattern, idx, CompareOptions.OrdinalIgnoreCase);
}
+ // Helpers
+
void CheckBaseAddress (Uri baseAddress)
{
if (baseAddress == null)
throw new ArgumentNullException ("baseAddress");
if (!baseAddress.IsAbsoluteUri)
- throw new ArgumentException ("baseAddress must be an
absolute URI.");
+ throw new ArgumentException ("baseAddress must
be an absolute URI.");
if (baseAddress.Scheme == Uri.UriSchemeHttp ||
baseAddress.Scheme == Uri.UriSchemeHttps)
return;
Modified: trunk/olive/class/System.ServiceModel.Web/System/UriTemplateMatch.cs
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/System/UriTemplateMatch.cs
2008-02-12 18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/System/UriTemplateMatch.cs
2008-02-12 18:22:50 UTC (rev 95540)
@@ -37,20 +37,27 @@
{
}
- [MonoTODO]
+ Uri base_uri;
+ NameValueCollection nvc;
+ object data;
+ UriTemplate template;
+
public Uri BaseUri {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
+ get { return base_uri; }
+ set { base_uri = value; }
}
- [MonoTODO]
public NameValueCollection BoundVariables {
- get { throw new NotImplementedException (); }
+ get {
+ if (nvc == null)
+ nvc = new NameValueCollection ();
+ return nvc;
+ }
}
public object Data {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
+ get { return data; }
+ set { data = value; }
}
[MonoTODO]
@@ -69,10 +76,9 @@
set { throw new NotImplementedException (); }
}
- [MonoTODO]
public UriTemplate Template {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
+ get { return template; }
+ set { template = value; }
}
public Collection<string> WildcardPathSegments {
Modified: trunk/olive/class/System.ServiceModel.Web/System/UriTemplateTable.cs
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/System/UriTemplateTable.cs
2008-02-12 18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/System/UriTemplateTable.cs
2008-02-12 18:22:50 UTC (rev 95540)
@@ -93,13 +93,26 @@
[MonoTODO]
public Collection<UriTemplateMatch> Match (Uri uri)
{
- throw new NotImplementedException ();
+ var c = new Collection<UriTemplateMatch> ();
+ UriTemplateMatch ret = null;
+ foreach (Pair p in key_value_pairs) {
+ ret = p.Key.Match (base_address, uri);
+ if (ret != null)
+ c.Add (ret);
+ }
+ return c;
}
[MonoTODO]
public UriTemplateMatch MatchSingle (Uri uri)
{
- throw new NotImplementedException ();
+ UriTemplateMatch ret = null;
+ foreach (Pair p in key_value_pairs) {
+ ret = p.Key.Match (base_address, uri);
+ if (ret != null)
+ return ret;
+ }
+ throw new UriTemplateMatchException (String.Format ("No
template matched for Uri '{0}'", uri));
}
}
}
Modified: trunk/olive/class/System.ServiceModel.Web/Test/System/ChangeLog
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/Test/System/ChangeLog
2008-02-12 18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/Test/System/ChangeLog
2008-02-12 18:22:50 UTC (rev 95540)
@@ -1,4 +1,8 @@
2008-02-12 Atsushi Enomoto <[EMAIL PROTECTED]>
+ * UriTemplateTest.cs : Added tests for Match() and more Binding tests.
+
+2008-02-12 Atsushi Enomoto <[EMAIL PROTECTED]>
+
* UriTemplateTest.cs : new. Test .ctor(), BindByName() and
BindByPosition().
Modified:
trunk/olive/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs
===================================================================
--- trunk/olive/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs
2008-02-12 18:10:52 UTC (rev 95539)
+++ trunk/olive/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs
2008-02-12 18:22:50 UTC (rev 95540)
@@ -69,20 +69,25 @@
var t = new UriTemplate ("urn:foo");
Assert.AreEqual (0, t.PathSegmentVariableNames.Count,
"#1a");
Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#1b");
+
t = new UriTemplate ("http://localhost:8080/");
Assert.AreEqual (0, t.PathSegmentVariableNames.Count,
"#2a");
Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#2b");
+
t = new UriTemplate ("http://localhost:8080/foo/");
Assert.AreEqual (0, t.PathSegmentVariableNames.Count,
"#3a");
Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#3b");
+
t = new UriTemplate ("http://localhost:8080/{foo}");
Assert.AreEqual (1, t.PathSegmentVariableNames.Count,
"#4a");
Assert.AreEqual ("FOO", t.PathSegmentVariableNames [0],
"#4b");
Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#4c");
+
t = new UriTemplate ("http://localhost:8080/{foo}/{");
Assert.AreEqual (1, t.PathSegmentVariableNames.Count,
"#5a");
Assert.AreEqual ("FOO", t.PathSegmentVariableNames [0],
"#5b");
Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#5c");
+
t = new UriTemplate
("http://localhost:8080/hoge?test={foo}&test2={bar}");
Assert.AreEqual (0, t.PathSegmentVariableNames.Count,
"#6a");
Assert.AreEqual (2, t.QueryValueVariableNames.Count,
"#6b");
@@ -91,6 +96,25 @@
}
[Test]
+ [Category ("NotWorking")]
+ public void VariablesInSameSegment ()
+ {
+ var t = new UriTemplate
("http://localhost:8080/{foo}{bar}");
+ Assert.AreEqual (1, t.PathSegmentVariableNames.Count,
"#7a");
+ // wow.
+ Assert.AreEqual ("FOO}{BAR", t.PathSegmentVariableNames
[0], "#7b");
+ Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#7c");
+ }
+
+ [Test]
+ public void VariablesInNonPathQuery ()
+ {
+ var t = new UriTemplate ("http://localhost:{foo}/");
+ Assert.AreEqual (0, t.PathSegmentVariableNames.Count,
"#8a");
+ Assert.AreEqual (0, t.QueryValueVariableNames.Count,
"#8b");
+ }
+
+ [Test]
[ExpectedException (typeof (InvalidOperationException))]
public void DuplicateNameInTemplate ()
{
@@ -148,6 +172,12 @@
}
[Test]
+ public void BindInSameSegment ()
+ {
+ new UriTemplate ("/hoo/{foo}{bar}");
+ }
+
+ [Test]
public void BindByName ()
{
var t = new UriTemplate ("/{foo}/{bar}/");
@@ -205,5 +235,43 @@
var u = t.BindByPosition (new Uri
("http://localhost/"), "value1", "value2");
Assert.AreEqual ("http://localhost/value1/value2/",
u.ToString ());
}
+
+ [Test]
+ public void MatchNoTemplateItem ()
+ {
+ var t = new UriTemplate ("/hooray");
+ var n = new NameValueCollection ();
+ Assert.IsNotNull (t.Match (new Uri
("http://localhost/"), new Uri ("http://localhost/hooray")), "#1");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/foobar")), "#2");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hooray/foobar")), "#3");
+ }
+
+ [Test]
+ public void MatchWrongTemplate ()
+ {
+ var t = new UriTemplate ("/hoo{foo}");
+ var n = new NameValueCollection ();
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hooray")), "#1");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/foobar")), "#2");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hooray/foobar")), "#3");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hoo/ray")), "#4");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hoo")), "#5");
+ // this matches (as if there were no template).
+ Assert.IsNotNull (t.Match (new Uri
("http://localhost/"), new Uri ("http://localhost/hoo{foo}")), "#6");
+ }
+
+ [Test]
+ public void Match ()
+ {
+ var t = new UriTemplate ("/{foo}/{bar}");
+ var n = new NameValueCollection ();
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/hooray")), "#1");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/v1/v2/extra")), "#2");
+ Assert.IsNull (t.Match (new Uri ("http://localhost/"),
new Uri ("http://localhost/1/2/")), "#3");
+ UriTemplateMatch m = t.Match (new Uri
("http://localhost/"), new Uri ("http://localhost/foooo/baaar"));
+ Assert.IsNotNull (m, "#4");
+ Assert.AreEqual ("foooo", m.BoundVariables ["foo"],
"#5");
+ Assert.AreEqual ("baaar", m.BoundVariables ["bar"],
"#6");
+ }
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches