static void Validate(UriTemplatePathPartiallyEquivalentSet pes, bool allowDuplicateEquivalentUriTemplates)
        {
            // A set with 0 or 1 items is valid by definition
            if (pes.Items.Count < 2)
            {
                return;
            }
            // Assert all paths are partially-equivalent
            for (int i = 0; i < pes.Items.Count - 1; ++i)
            {
                Fx.Assert(pes.Items[i].Key.IsPathPartiallyEquivalentAt(pes.Items[i + 1].Key, pes.SegmentsCount),
                          "all elements of a PES must be path partially-equivalent");
            }
            // We will check that the queries disambiguate only for templates, which are
            //  matched completely at the segments count; templates, which are match at
            //  that point due to terminal defaults, will be ruled out.
            UriTemplate[] a          = new UriTemplate[pes.Items.Count];
            int           arrayIndex = 0;

            foreach (KeyValuePair <UriTemplate, object> kvp in pes.Items)
            {
                if (pes.SegmentsCount < kvp.Key.segments.Count)
                {
                    continue;
                }
                Fx.Assert(arrayIndex < a.Length, "We made enough room for all the items");
                a[arrayIndex++] = kvp.Key;
            }
            // Ensure that queries disambiguate (if needed) :
            if (arrayIndex > 0)
            {
                UriTemplateHelpers.DisambiguateSamePath(a, 0, arrayIndex, allowDuplicateEquivalentUriTemplates);
            }
        }
        UriTemplatePathPartiallyEquivalentSet star;                                                             // matches any "extra/path/segments" at the end

        UriTemplateTrieNode(int depth)
        {
            this.depth = depth;
            this.nextLiteralSegment   = null;
            this.nextCompoundSegment  = null;
            this.finalLiteralSegment  = null;
            this.finalCompoundSegment = null;
            this.finalVariableSegment = new UriTemplatePathPartiallyEquivalentSet(depth + 1);
            this.star      = new UriTemplatePathPartiallyEquivalentSet(depth);
            this.endOfPath = new UriTemplatePathPartiallyEquivalentSet(depth);
        }
        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 AddFinalCompoundSegment(UriTemplateCompoundPathSegment cps, KeyValuePair <UriTemplate, object> kvp)
        {
            if (this.finalCompoundSegment == null)
            {
                this.finalCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet>();
            }
            UriTemplatePathPartiallyEquivalentSet set = this.finalCompoundSegment.Find(cps);

            if (set == null)
            {
                set = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1);
                this.finalCompoundSegment.Add(cps, set);
            }
            set.Items.Add(kvp);
        }
        void AddFinalCompoundSegment(UriTemplateCompoundPathSegment cps, KeyValuePair <UriTemplate, object> kvp)
        {
            Fx.Assert(cps != null, "must be - based on the segment nature");
            if (this.finalCompoundSegment == null)
            {
                this.finalCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet>();
            }
            UriTemplatePathPartiallyEquivalentSet pes = this.finalCompoundSegment.Find(cps);

            if (pes == null)
            {
                pes = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1);
                this.finalCompoundSegment.Add(cps, pes);
            }
            pes.Items.Add(kvp);
        }
 private void AddFinalLiteralSegment(UriTemplateLiteralPathSegment lps, KeyValuePair <UriTemplate, object> kvp)
 {
     if ((this.finalLiteralSegment != null) && this.finalLiteralSegment.ContainsKey(lps))
     {
         this.finalLiteralSegment[lps].Items.Add(kvp);
     }
     else
     {
         if (this.finalLiteralSegment == null)
         {
             this.finalLiteralSegment = new Dictionary <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet>();
         }
         UriTemplatePathPartiallyEquivalentSet set = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1);
         set.Items.Add(kvp);
         this.finalLiteralSegment.Add(lps, set);
     }
 }
 void AddFinalLiteralSegment(UriTemplateLiteralPathSegment lps, KeyValuePair <UriTemplate, object> kvp)
 {
     Fx.Assert(lps != null, "must be - based on the segment nature");
     if (this.finalLiteralSegment != null && this.finalLiteralSegment.ContainsKey(lps))
     {
         this.finalLiteralSegment[lps].Items.Add(kvp);
     }
     else
     {
         if (this.finalLiteralSegment == null)
         {
             this.finalLiteralSegment = new Dictionary <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet>();
         }
         UriTemplatePathPartiallyEquivalentSet pes = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1);
         pes.Items.Add(kvp);
         this.finalLiteralSegment.Add(lps, pes);
     }
 }
 private static void Validate(UriTemplatePathPartiallyEquivalentSet pes, bool allowDuplicateEquivalentUriTemplates)
 {
     if (pes.Items.Count >= 2)
     {
         for (int i = 0; i < (pes.Items.Count - 1); i++)
         {
         }
         UriTemplate[] array = new UriTemplate[pes.Items.Count];
         int           b     = 0;
         foreach (KeyValuePair <UriTemplate, object> pair in pes.Items)
         {
             if (pes.SegmentsCount >= pair.Key.segments.Count)
             {
                 array[b++] = pair.Key;
             }
         }
         if (b > 0)
         {
             UriTemplateHelpers.DisambiguateSamePath(array, 0, b, allowDuplicateEquivalentUriTemplates);
         }
     }
 }
        static bool TryMatch(UriTemplateLiteralPathSegment[] wireUriSegments, UriTemplateTrieLocation currentLocation,
                             out UriTemplatePathPartiallyEquivalentSet success, out SingleLocationOrLocationsSet nextStep)
        {
            // if returns true, success is set to answer
            // if returns false, nextStep is set to next place to look
            success  = null;
            nextStep = new SingleLocationOrLocationsSet();

            if (wireUriSegments.Length <= currentLocation.node.depth)
            {
                Fx.Assert(wireUriSegments.Length == 0 || wireUriSegments[wireUriSegments.Length - 1].EndsWithSlash,
                          "we should not have traversed this deep into the trie unless the wire path ended in a slash");

                if (currentLocation.node.endOfPath.Items.Count != 0)
                {
                    // exact match of e.g. "path1/path2/"
                    success = currentLocation.node.endOfPath;
                    return(true);
                }
                else if (currentLocation.node.star.Items.Count != 0)
                {
                    // inexact match of e.g. WIRE("path1/path2/") against TEMPLATE("path1/path2/*")
                    success = currentLocation.node.star;
                    return(true);
                }
                else
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                    return(false);
                }
            }
            else
            {
                UriTemplateLiteralPathSegment curWireSeg = wireUriSegments[currentLocation.node.depth];
                bool considerLiteral  = false;
                bool considerCompound = false;
                bool considerVariable = false;
                bool considerStar     = false;
                switch (currentLocation.locationWithin)
                {
                case UriTemplateTrieIntraNodeLocation.BeforeLiteral:
                    considerLiteral  = true;
                    considerCompound = true;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterLiteral:
                    considerLiteral  = false;
                    considerCompound = true;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterCompound:
                    considerLiteral  = false;
                    considerCompound = false;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterVariable:
                    considerLiteral  = false;
                    considerCompound = false;
                    considerVariable = false;
                    considerStar     = true;
                    break;

                default:
                    Fx.Assert("bad kind");
                    break;
                }
                if (curWireSeg.EndsWithSlash)
                {
                    IList <IList <UriTemplateTrieLocation> > compoundLocationsSet;

                    if (considerLiteral && currentLocation.node.nextLiteralSegment != null &&
                        currentLocation.node.nextLiteralSegment.ContainsKey(curWireSeg))
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextLiteralSegment[curWireSeg]);
                        return(false);
                    }
                    else if (considerCompound && currentLocation.node.nextCompoundSegment != null &&
                             AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation> .Lookup(currentLocation.node.nextCompoundSegment, curWireSeg, out compoundLocationsSet))
                    {
                        nextStep = new SingleLocationOrLocationsSet(compoundLocationsSet);
                        return(false);
                    }
                    else if (considerVariable && currentLocation.node.nextVariableSegment != null &&
                             !curWireSeg.IsNullOrEmpty())
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextVariableSegment);
                        return(false);
                    }
                    else if (considerStar && currentLocation.node.star.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2/path3") and TEMPLATE("path1/*")
                        success = currentLocation.node.star;
                        return(true);
                    }
                    else
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                        return(false);
                    }
                }
                else
                {
                    IList <IList <UriTemplatePathPartiallyEquivalentSet> > compoundPathEquivalentSets;

                    Fx.Assert(!curWireSeg.EndsWithSlash, "!curWireSeg.EndsWithSlash");
                    Fx.Assert(!curWireSeg.IsNullOrEmpty(), "!curWireSeg.IsNullOrEmpty()");
                    if (considerLiteral && currentLocation.node.finalLiteralSegment != null &&
                        currentLocation.node.finalLiteralSegment.ContainsKey(curWireSeg))
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/path2")
                        success = currentLocation.node.finalLiteralSegment[curWireSeg];
                        return(true);
                    }
                    else if (considerCompound && currentLocation.node.finalCompoundSegment != null &&
                             AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet> .Lookup(currentLocation.node.finalCompoundSegment, curWireSeg, out compoundPathEquivalentSets))
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/p{var}th2")
                        // we should take only the highest order match!
                        Fx.Assert(compoundPathEquivalentSets.Count >= 1, "Lookup is expected to return false otherwise");
                        Fx.Assert(compoundPathEquivalentSets[0].Count > 0, "Find shouldn't return empty sublists");
                        if (compoundPathEquivalentSets[0].Count == 1)
                        {
                            success = compoundPathEquivalentSets[0][0];
                        }
                        else
                        {
                            success = new UriTemplatePathPartiallyEquivalentSet(currentLocation.node.depth + 1);
                            for (int i = 0; i < compoundPathEquivalentSets[0].Count; i++)
                            {
                                success.Items.AddRange(compoundPathEquivalentSets[0][i].Items);
                            }
                        }
                        return(true);
                    }
                    else if (considerVariable && currentLocation.node.finalVariableSegment.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/{var}")
                        success = currentLocation.node.finalVariableSegment;
                        return(true);
                    }
                    else if (considerStar && currentLocation.node.star.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/*")
                        success = currentLocation.node.star;
                        return(true);
                    }
                    else
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                        return(false);
                    }
                }
            }
        }
        private static bool TryMatch(UriTemplateLiteralPathSegment[] wireUriSegments, UriTemplateTrieLocation currentLocation, out UriTemplatePathPartiallyEquivalentSet success, out SingleLocationOrLocationsSet nextStep)
        {
            IList <IList <UriTemplatePathPartiallyEquivalentSet> > list2;

            success  = null;
            nextStep = new SingleLocationOrLocationsSet();
            if (wireUriSegments.Length <= currentLocation.node.depth)
            {
                if (currentLocation.node.endOfPath.Items.Count != 0)
                {
                    success = currentLocation.node.endOfPath;
                    return(true);
                }
                if (currentLocation.node.star.Items.Count != 0)
                {
                    success = currentLocation.node.star;
                    return(true);
                }
                nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                return(false);
            }
            UriTemplateLiteralPathSegment key = wireUriSegments[currentLocation.node.depth];
            bool flag  = false;
            bool flag2 = false;
            bool flag3 = false;
            bool flag4 = false;

            switch (currentLocation.locationWithin)
            {
            case UriTemplateTrieIntraNodeLocation.BeforeLiteral:
                flag  = true;
                flag2 = true;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterLiteral:
                flag  = false;
                flag2 = true;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterCompound:
                flag  = false;
                flag2 = false;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterVariable:
                flag  = false;
                flag2 = false;
                flag3 = false;
                flag4 = true;
                break;
            }
            if (key.EndsWithSlash)
            {
                IList <IList <UriTemplateTrieLocation> > list;
                if ((flag && (currentLocation.node.nextLiteralSegment != null)) && currentLocation.node.nextLiteralSegment.ContainsKey(key))
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextLiteralSegment[key]);
                    return(false);
                }
                if ((flag2 && (currentLocation.node.nextCompoundSegment != null)) && AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation> .Lookup(currentLocation.node.nextCompoundSegment, key, out list))
                {
                    nextStep = new SingleLocationOrLocationsSet(list);
                    return(false);
                }
                if ((flag3 && (currentLocation.node.nextVariableSegment != null)) && !key.IsNullOrEmpty())
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextVariableSegment);
                    return(false);
                }
                if (flag4 && (currentLocation.node.star.Items.Count != 0))
                {
                    success = currentLocation.node.star;
                    return(true);
                }
                nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                return(false);
            }
            if ((flag && (currentLocation.node.finalLiteralSegment != null)) && currentLocation.node.finalLiteralSegment.ContainsKey(key))
            {
                success = currentLocation.node.finalLiteralSegment[key];
                return(true);
            }
            if ((flag2 && (currentLocation.node.finalCompoundSegment != null)) && AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet> .Lookup(currentLocation.node.finalCompoundSegment, key, out list2))
            {
                if (list2[0].Count == 1)
                {
                    success = list2[0][0];
                }
                else
                {
                    success = new UriTemplatePathPartiallyEquivalentSet(currentLocation.node.depth + 1);
                    for (int i = 0; i < list2[0].Count; i++)
                    {
                        success.Items.AddRange(list2[0][i].Items);
                    }
                }
                return(true);
            }
            if (flag3 && (currentLocation.node.finalVariableSegment.Items.Count != 0))
            {
                success = currentLocation.node.finalVariableSegment;
                return(true);
            }
            if (flag4 && (currentLocation.node.star.Items.Count != 0))
            {
                success = currentLocation.node.star;
                return(true);
            }
            nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
            return(false);
        }