public static void Main() { Uri prefix = new Uri("http://localhost/"); //A UriTemplate is a "URI with holes". It describes a set of URI's that //are structurally similar. This UriTemplate might be used for organizing //weather reports: UriTemplate template = new UriTemplate("weather/{state}/{city}"); //You can convert a UriTemplate into a Uri by filling //the holes in the template with parameters. //BindByPosition moves left-to-right across the template Uri positionalUri = template.BindByPosition(prefix, "Washington", "Redmond"); Console.WriteLine("Calling BindByPosition..."); Console.WriteLine(positionalUri); Console.WriteLine(); //BindByName takes a NameValueCollection of parameters. //Each parameter gets substituted into the UriTemplate "hole" //that has the same name as the parameter. NameValueCollection parameters = new NameValueCollection(); parameters.Add("state", "Washington"); parameters.Add("city", "Redmond"); Uri namedUri = template.BindByName(prefix, parameters); Console.WriteLine("Calling BindByName..."); Console.WriteLine(namedUri); Console.WriteLine(); //The inverse operation of Bind is Match(), which extrudes a URI //through the template to produce a set of name/value pairs. Uri fullUri = new Uri("http://localhost/weather/Washington/Redmond"); UriTemplateMatch results = template.Match(prefix, fullUri); Console.WriteLine(String.Format("Matching {0} to {1}", template.ToString(), fullUri.ToString())); if (results != null) { foreach (string variableName in results.BoundVariables.Keys) { Console.WriteLine(String.Format(" {0}: {1}", variableName, results.BoundVariables[variableName])); } } Console.WriteLine("Press any key to terminate"); Console.ReadLine(); }
static void Validate(UriTemplateTrieNode root, bool allowDuplicateEquivalentUriTemplates) { // walk the entire tree, and ensure that each PathEquivalentSet is ok (no ambiguous queries), // verify thst compound segments didn't add potentialy multiple matchs; // also Assert various data-structure invariants Queue <UriTemplateTrieNode> nodesQueue = new Queue <UriTemplateTrieNode>(); UriTemplateTrieNode current = root; while (true) { // validate all the PathEquivalentSets that live in this node Validate(current.endOfPath, allowDuplicateEquivalentUriTemplates); Validate(current.finalVariableSegment, allowDuplicateEquivalentUriTemplates); Validate(current.star, allowDuplicateEquivalentUriTemplates); if (current.finalLiteralSegment != null) { foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet> kvp in current.finalLiteralSegment) { Validate(kvp.Value, allowDuplicateEquivalentUriTemplates); } } if (current.finalCompoundSegment != null) { IList <IList <UriTemplatePathPartiallyEquivalentSet> > pesLists = current.finalCompoundSegment.Values; for (int i = 0; i < pesLists.Count; i++) { if (!allowDuplicateEquivalentUriTemplates && (pesLists[i].Count > 1)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString( SR.UTTDuplicate, pesLists[i][0].Items[0].Key.ToString(), pesLists[i][1].Items[0].Key.ToString()))); } for (int j = 0; j < pesLists[i].Count; j++) { Validate(pesLists[i][j], allowDuplicateEquivalentUriTemplates); } } } // deal with children of this node if (current.nextLiteralSegment != null) { foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplateTrieLocation> kvp in current.nextLiteralSegment) { Fx.Assert(kvp.Value.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); Fx.Assert(kvp.Value.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1"); Fx.Assert(kvp.Value.node.onFailure.node == current, "back pointer should point back to here"); Fx.Assert(kvp.Value.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterLiteral, "back-pointer should be AfterLiteral"); nodesQueue.Enqueue(kvp.Value.node); } } if (current.nextCompoundSegment != null) { IList <IList <UriTemplateTrieLocation> > locations = current.nextCompoundSegment.Values; for (int i = 0; i < locations.Count; i++) { if (!allowDuplicateEquivalentUriTemplates && (locations[i].Count > 1)) { // In the future we might ease up the restrictions and verify if there is realy // a potential multiple match here; for now we are throwing. UriTemplate firstTemplate = FindAnyUriTemplate(locations[i][0].node); UriTemplate secondTemplate = FindAnyUriTemplate(locations[i][1].node); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString( SR.UTTDuplicate, firstTemplate.ToString(), secondTemplate.ToString()))); } for (int j = 0; j < locations[i].Count; j++) { UriTemplateTrieLocation location = locations[i][j]; Fx.Assert(location.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); Fx.Assert(location.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1"); Fx.Assert(location.node.onFailure.node == current, "back pointer should point back to here"); Fx.Assert(location.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterCompound, "back-pointer should be AfterCompound"); nodesQueue.Enqueue(location.node); } } } if (current.nextVariableSegment != null) { Fx.Assert(current.nextVariableSegment.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); Fx.Assert(current.nextVariableSegment.node.depth == current.depth + 1, "current.nextVariableSegment.node.depth == current.depth + 1"); Fx.Assert(current.nextVariableSegment.node.onFailure.node == current, "back pointer should point back to here"); Fx.Assert(current.nextVariableSegment.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterVariable, "back-pointer should be AfterVariable"); nodesQueue.Enqueue(current.nextVariableSegment.node); } // move on to next bit of work if (nodesQueue.Count == 0) { break; } current = nodesQueue.Dequeue(); } }
private static void Validate(UriTemplateTrieNode root, bool allowDuplicateEquivalentUriTemplates) { Queue <UriTemplateTrieNode> queue = new Queue <UriTemplateTrieNode>(); UriTemplateTrieNode node = root; while (true) { Validate(node.endOfPath, allowDuplicateEquivalentUriTemplates); Validate(node.finalVariableSegment, allowDuplicateEquivalentUriTemplates); Validate(node.star, allowDuplicateEquivalentUriTemplates); if (node.finalLiteralSegment != null) { foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet> pair in node.finalLiteralSegment) { Validate(pair.Value, allowDuplicateEquivalentUriTemplates); } } if (node.finalCompoundSegment != null) { IList <IList <UriTemplatePathPartiallyEquivalentSet> > values = node.finalCompoundSegment.Values; for (int i = 0; i < values.Count; i++) { if (!allowDuplicateEquivalentUriTemplates && (values[i].Count > 1)) { object[] args = new object[2]; KeyValuePair <UriTemplate, object> pair3 = values[i][0].Items[0]; args[0] = pair3.Key.ToString(); KeyValuePair <UriTemplate, object> pair4 = values[i][1].Items[0]; args[1] = pair4.Key.ToString(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTDuplicate", args))); } for (int j = 0; j < values[i].Count; j++) { Validate(values[i][j], allowDuplicateEquivalentUriTemplates); } } } if (node.nextLiteralSegment != null) { foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplateTrieLocation> pair2 in node.nextLiteralSegment) { queue.Enqueue(pair2.Value.node); } } if (node.nextCompoundSegment != null) { IList <IList <UriTemplateTrieLocation> > list2 = node.nextCompoundSegment.Values; for (int k = 0; k < list2.Count; k++) { if (!allowDuplicateEquivalentUriTemplates && (list2[k].Count > 1)) { UriTemplate template = FindAnyUriTemplate(list2[k][0].node); UriTemplate template2 = FindAnyUriTemplate(list2[k][1].node); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTDuplicate", new object[] { template.ToString(), template2.ToString() }))); } for (int m = 0; m < list2[k].Count; m++) { UriTemplateTrieLocation location = list2[k][m]; queue.Enqueue(location.node); } } } if (node.nextVariableSegment != null) { queue.Enqueue(node.nextVariableSegment.node); } if (queue.Count == 0) { return; } node = queue.Dequeue(); } }