private static void Add(UriTemplateTrieNode root, KeyValuePair <UriTemplate, object> kvp)
        {
            UriTemplateTrieNode node = root;
            UriTemplate         key  = kvp.Key;
            bool flag = ((key.segments.Count == 0) || key.HasWildcard) || key.segments[key.segments.Count - 1].EndsWithSlash;

            for (int i = 0; i < key.segments.Count; i++)
            {
                if (i >= key.firstOptionalSegment)
                {
                    node.endOfPath.Items.Add(kvp);
                }
                UriTemplatePathSegment segment = key.segments[i];
                if (!segment.EndsWithSlash)
                {
                    switch (segment.Nature)
                    {
                    case UriTemplatePartType.Literal:
                        node.AddFinalLiteralSegment(segment as UriTemplateLiteralPathSegment, kvp);
                        break;

                    case UriTemplatePartType.Compound:
                        node.AddFinalCompoundSegment(segment as UriTemplateCompoundPathSegment, kvp);
                        break;

                    case UriTemplatePartType.Variable:
                        node.finalVariableSegment.Items.Add(kvp);
                        break;
                    }
                }
                else
                {
                    switch (segment.Nature)
                    {
                    case UriTemplatePartType.Literal:
                        node = node.AddNextLiteralSegment(segment as UriTemplateLiteralPathSegment);
                        break;

                    case UriTemplatePartType.Compound:
                        node = node.AddNextCompoundSegment(segment as UriTemplateCompoundPathSegment);
                        break;

                    case UriTemplatePartType.Variable:
                        node = node.AddNextVariableSegment();
                        break;
                    }
                }
            }
            if (flag)
            {
                if (key.HasWildcard)
                {
                    node.star.Items.Add(kvp);
                }
                else
                {
                    node.endOfPath.Items.Add(kvp);
                }
            }
        }
        public static UriTemplateTrieNode Make(IEnumerable <KeyValuePair <UriTemplate, object> > keyValuePairs, bool allowDuplicateEquivalentUriTemplates)
        {
            UriTemplateTrieNode root = new UriTemplateTrieNode(0);

            foreach (KeyValuePair <UriTemplate, object> pair in keyValuePairs)
            {
                Add(root, pair);
            }
            Validate(root, allowDuplicateEquivalentUriTemplates);
            return(root);
        }
Пример #3
0
        static UriTemplate FindAnyUriTemplate(UriTemplateTrieNode node)
        {
            while (node != null)
            {
                if (node.endOfPath.Items.Count > 0)
                {
                    return(node.endOfPath.Items[0].Key);
                }
                if (node.finalVariableSegment.Items.Count > 0)
                {
                    return(node.finalVariableSegment.Items[0].Key);
                }
                if (node.star.Items.Count > 0)
                {
                    return(node.star.Items[0].Key);
                }
                if (node.finalLiteralSegment != null)
                {
                    UriTemplatePathPartiallyEquivalentSet pes =
                        GetAnyDictionaryValue <UriTemplatePathPartiallyEquivalentSet>(node.finalLiteralSegment);
                    Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the dictionary?");
                    return(pes.Items[0].Key);
                }
                if (node.finalCompoundSegment != null)
                {
                    UriTemplatePathPartiallyEquivalentSet pes = node.finalCompoundSegment.GetAnyValue();
                    Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the collection?");
                    return(pes.Items[0].Key);
                }

                if (node.nextLiteralSegment != null)
                {
                    UriTemplateTrieLocation location =
                        GetAnyDictionaryValue <UriTemplateTrieLocation>(node.nextLiteralSegment);
                    node = location.node;
                }
                else if (node.nextCompoundSegment != null)
                {
                    UriTemplateTrieLocation location = node.nextCompoundSegment.GetAnyValue();
                    node = location.node;
                }
                else if (node.nextVariableSegment != null)
                {
                    node = node.nextVariableSegment.node;
                }
                else
                {
                    node = null;
                }
            }
            Fx.Assert("How did we got here without finding a UriTemplate earlier?");
            return(null);
        }
 private void Validate(bool allowDuplicateEquivalentUriTemplates)
 {
     if (this.baseAddress == null)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTBaseAddressNotSet")));
     }
     this.numSegmentsInBaseAddress = this.baseAddress.Segments.Length;
     if (this.templates.Count == 0)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTEmptyKeyValuePairs")));
     }
     this.rootNode = UriTemplateTrieNode.Make(this.templates, allowDuplicateEquivalentUriTemplates);
 }
Пример #5
0
 UriTemplateTrieNode AddNextVariableSegment()
 {
     if (this.nextVariableSegment != null)
     {
         return(this.nextVariableSegment.node);
     }
     else
     {
         UriTemplateTrieNode newNode = new UriTemplateTrieNode(this.depth + 1);
         newNode.onFailure        = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterVariable);
         this.nextVariableSegment = new UriTemplateTrieLocation(newNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
         return(newNode);
     }
 }
Пример #6
0
        public static UriTemplateTrieNode Make(IEnumerable <KeyValuePair <UriTemplate, object> > keyValuePairs,
                                               bool allowDuplicateEquivalentUriTemplates)
        {
            // given a UTT at MakeReadOnly time, build the trie
            // note that root.onFailure == null;
            UriTemplateTrieNode root = new UriTemplateTrieNode(0);

            foreach (KeyValuePair <UriTemplate, object> kvp in keyValuePairs)
            {
                Add(root, kvp);
            }
            Validate(root, allowDuplicateEquivalentUriTemplates);
            return(root);
        }
 private static UriTemplate FindAnyUriTemplate(UriTemplateTrieNode node)
 {
     while (node != null)
     {
         if (node.endOfPath.Items.Count > 0)
         {
             KeyValuePair <UriTemplate, object> pair = node.endOfPath.Items[0];
             return(pair.Key);
         }
         if (node.finalVariableSegment.Items.Count > 0)
         {
             KeyValuePair <UriTemplate, object> pair2 = node.finalVariableSegment.Items[0];
             return(pair2.Key);
         }
         if (node.star.Items.Count > 0)
         {
             KeyValuePair <UriTemplate, object> pair3 = node.star.Items[0];
             return(pair3.Key);
         }
         if (node.finalLiteralSegment != null)
         {
             KeyValuePair <UriTemplate, object> pair4 = GetAnyDictionaryValue <UriTemplatePathPartiallyEquivalentSet>(node.finalLiteralSegment).Items[0];
             return(pair4.Key);
         }
         if (node.finalCompoundSegment != null)
         {
             KeyValuePair <UriTemplate, object> pair5 = node.finalCompoundSegment.GetAnyValue().Items[0];
             return(pair5.Key);
         }
         if (node.nextLiteralSegment != null)
         {
             node = GetAnyDictionaryValue <UriTemplateTrieLocation>(node.nextLiteralSegment).node;
         }
         else
         {
             if (node.nextCompoundSegment != null)
             {
                 node = node.nextCompoundSegment.GetAnyValue().node;
                 continue;
             }
             if (node.nextVariableSegment != null)
             {
                 node = node.nextVariableSegment.node;
                 continue;
             }
             node = null;
         }
     }
     return(null);
 }
        private UriTemplateTrieNode AddNextVariableSegment()
        {
            if (this.nextVariableSegment != null)
            {
                return(this.nextVariableSegment.node);
            }
            UriTemplateTrieNode n = new UriTemplateTrieNode(this.depth + 1)
            {
                onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterVariable)
            };

            this.nextVariableSegment = new UriTemplateTrieLocation(n, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
            return(n);
        }
Пример #9
0
 void Validate(bool allowDuplicateEquivalentUriTemplates)
 {
     if (this.baseAddress == null)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
                                                                                                     SR.UTTBaseAddressNotSet)));
     }
     this.numSegmentsInBaseAddress = this.baseAddress.Segments.Length;
     if (this.templates.Count == 0)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
                                                                                                     SR.UTTEmptyKeyValuePairs)));
     }
     // build the trie and
     // validate that forall Uri u, at most one UriTemplate is a best match for u
     rootNode = UriTemplateTrieNode.Make(this.templates, allowDuplicateEquivalentUriTemplates);
 }
Пример #10
0
        UriTemplateTrieNode AddNextCompoundSegment(UriTemplateCompoundPathSegment cps)
        {
            Fx.Assert(cps != null, "must be - based on the segment nature");
            if (this.nextCompoundSegment == null)
            {
                this.nextCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation>();
            }
            UriTemplateTrieLocation nextLocation = this.nextCompoundSegment.Find(cps);

            if (nextLocation == null)
            {
                UriTemplateTrieNode nextNode = new UriTemplateTrieNode(this.depth + 1);
                nextNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterCompound);
                nextLocation       = new UriTemplateTrieLocation(nextNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
                this.nextCompoundSegment.Add(cps, nextLocation);
            }
            return(nextLocation.node);
        }
        private UriTemplateTrieNode AddNextLiteralSegment(UriTemplateLiteralPathSegment lps)
        {
            if ((this.nextLiteralSegment != null) && this.nextLiteralSegment.ContainsKey(lps))
            {
                return(this.nextLiteralSegment[lps].node);
            }
            if (this.nextLiteralSegment == null)
            {
                this.nextLiteralSegment = new Dictionary <UriTemplateLiteralPathSegment, UriTemplateTrieLocation>();
            }
            UriTemplateTrieNode n = new UriTemplateTrieNode(this.depth + 1)
            {
                onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterLiteral)
            };

            this.nextLiteralSegment.Add(lps, new UriTemplateTrieLocation(n, UriTemplateTrieIntraNodeLocation.BeforeLiteral));
            return(n);
        }
Пример #12
0
 UriTemplateTrieNode AddNextLiteralSegment(UriTemplateLiteralPathSegment lps)
 {
     Fx.Assert(lps != null, "must be - based on the segment nature");
     if (this.nextLiteralSegment != null && this.nextLiteralSegment.ContainsKey(lps))
     {
         return(this.nextLiteralSegment[lps].node);
     }
     else
     {
         if (this.nextLiteralSegment == null)
         {
             this.nextLiteralSegment = new Dictionary <UriTemplateLiteralPathSegment, UriTemplateTrieLocation>();
         }
         UriTemplateTrieNode newNode = new UriTemplateTrieNode(this.depth + 1);
         newNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterLiteral);
         this.nextLiteralSegment.Add(lps, new UriTemplateTrieLocation(newNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral));
         return(newNode);
     }
 }
        private UriTemplateTrieNode AddNextCompoundSegment(UriTemplateCompoundPathSegment cps)
        {
            if (this.nextCompoundSegment == null)
            {
                this.nextCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation>();
            }
            UriTemplateTrieLocation location = this.nextCompoundSegment.Find(cps);

            if (location == null)
            {
                UriTemplateTrieNode n = new UriTemplateTrieNode(this.depth + 1)
                {
                    onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterCompound)
                };
                location = new UriTemplateTrieLocation(n, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
                this.nextCompoundSegment.Add(cps, location);
            }
            return(location.node);
        }
Пример #14
0
        static void Add(UriTemplateTrieNode root, KeyValuePair <UriTemplate, object> kvp)
        {
            // Currently UTT doesn't support teplates with ignoreTrailingSlash == true; thus we
            //  don't care about supporting it in the trie as well.
            UriTemplateTrieNode current    = root;
            UriTemplate         ut         = kvp.Key;
            bool needProcessingOnFinalNode = ((ut.segments.Count == 0) || ut.HasWildcard ||
                                              ut.segments[ut.segments.Count - 1].EndsWithSlash);

            for (int i = 0; i < ut.segments.Count; ++i)
            {
                if (i >= ut.firstOptionalSegment)
                {
                    current.endOfPath.Items.Add(kvp);
                }
                UriTemplatePathSegment ps = ut.segments[i];
                if (!ps.EndsWithSlash)
                {
                    Fx.Assert(i == ut.segments.Count - 1, "only the last segment can !EndsWithSlash");
                    Fx.Assert(!ut.HasWildcard, "path star cannot have !EndsWithSlash");
                    switch (ps.Nature)
                    {
                    case UriTemplatePartType.Literal:
                        current.AddFinalLiteralSegment(ps as UriTemplateLiteralPathSegment, kvp);
                        break;

                    case UriTemplatePartType.Compound:
                        current.AddFinalCompoundSegment(ps as UriTemplateCompoundPathSegment, kvp);
                        break;

                    case UriTemplatePartType.Variable:
                        current.finalVariableSegment.Items.Add(kvp);
                        break;

                    default:
                        Fx.Assert("Invalid value as PathSegment.Nature");
                        break;
                    }
                }
                else
                {
                    Fx.Assert(ps.EndsWithSlash, "ps.EndsWithSlash");
                    switch (ps.Nature)
                    {
                    case UriTemplatePartType.Literal:
                        current = current.AddNextLiteralSegment(ps as UriTemplateLiteralPathSegment);
                        break;

                    case UriTemplatePartType.Compound:
                        current = current.AddNextCompoundSegment(ps as UriTemplateCompoundPathSegment);
                        break;

                    case UriTemplatePartType.Variable:
                        current = current.AddNextVariableSegment();
                        break;

                    default:
                        Fx.Assert("Invalid value as PathSegment.Nature");
                        break;
                    }
                }
            }
            if (needProcessingOnFinalNode)
            {
                // if the last segment ended in a slash, there is still more to do
                if (ut.HasWildcard)
                {
                    // e.g. "path1/path2/*"
                    current.star.Items.Add(kvp);
                }
                else
                {
                    // e.g. "path1/path2/"
                    current.endOfPath.Items.Add(kvp);
                }
            }
        }
Пример #15
0
        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();
            }
        }