/// <summary>
        /// Creates a new <see cref="ActionSelectionDecisionTree"/>.
        /// </summary>
        /// <param name="actions">The <see cref="ActionDescriptorCollection"/>.</param>
        public ActionSelectionDecisionTree(ActionDescriptorCollection actions)
        {
            Version = actions.Version;

            _root = DecisionTreeBuilder <ActionDescriptor> .GenerateTree(
                actions.Items,
                new ActionDescriptorClassifier());
        }
        /// <summary>
        /// Creates a new <see cref="ActionSelectionDecisionTree"/>.
        /// </summary>
        /// <param name="actions">The <see cref="ActionDescriptorCollection"/>.</param>
        public ActionSelectionDecisionTree(ActionDescriptorCollection actions)
        {
            Version = actions.Version;

            var conventionalRoutedActions = actions.Items.Where(a => a.AttributeRouteInfo?.Template == null).ToArray();

            _root = DecisionTreeBuilder <ActionDescriptor> .GenerateTree(
                conventionalRoutedActions,
                new ActionDescriptorClassifier());
        }
예제 #3
0
    public void BuildTree_WithMultipleItems()
    {
        // Arrange
        var items = new List <Item>();

        var item1 = new Item();

        item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy"));
        items.Add(item1);

        var item2 = new Item();

        item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout"));
        items.Add(item2);

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Matches);

        var action = Assert.Single(tree.Criteria);

        Assert.Equal("action", action.Key);

        var buy = action.Branches["Buy"];

        Assert.Empty(buy.Matches);

        var controller = Assert.Single(buy.Criteria);

        Assert.Equal("controller", controller.Key);

        var store = Assert.Single(controller.Branches);

        Assert.Equal("Store", store.Key);
        Assert.Empty(store.Value.Criteria);
        Assert.Same(item1, Assert.Single(store.Value.Matches));

        var checkout = action.Branches["Checkout"];

        Assert.Empty(checkout.Matches);

        controller = Assert.Single(checkout.Criteria);
        Assert.Equal("controller", controller.Key);

        store = Assert.Single(controller.Branches);
        Assert.Equal("Store", store.Key);
        Assert.Empty(store.Value.Criteria);
        Assert.Same(item2, Assert.Single(store.Value.Matches));
    }
예제 #4
0
    public void BuildTree_Empty()
    {
        // Arrange
        var items = new List <Item>();

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Criteria);
        Assert.Empty(tree.Matches);
    }
예제 #5
0
    public void BuildTree_TrivialMatch()
    {
        // Arrange
        var items = new List <Item>();

        var item = new Item();

        items.Add(item);

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Criteria);
        Assert.Same(item, Assert.Single(tree.Matches));
    }
예제 #6
0
    public void BuildTree_WithMultipleCriteria()
    {
        // Arrange
        var items = new List <Item>();

        var item = new Item();

        item.Criteria.Add("area", new DecisionCriterionValue(value: "Admin"));
        item.Criteria.Add("controller", new DecisionCriterionValue(value: "Users"));
        item.Criteria.Add("action", new DecisionCriterionValue(value: "AddUser"));
        items.Add(item);

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Matches);

        var area = Assert.Single(tree.Criteria);

        Assert.Equal("area", area.Key);

        var admin = Assert.Single(area.Branches);

        Assert.Equal("Admin", admin.Key);
        Assert.Empty(admin.Value.Matches);

        var controller = Assert.Single(admin.Value.Criteria);

        Assert.Equal("controller", controller.Key);

        var users = Assert.Single(controller.Branches);

        Assert.Equal("Users", users.Key);
        Assert.Empty(users.Value.Matches);

        var action = Assert.Single(users.Value.Criteria);

        Assert.Equal("action", action.Key);

        var addUser = Assert.Single(action.Branches);

        Assert.Equal("AddUser", addUser.Key);
        Assert.Empty(addUser.Value.Criteria);
        Assert.Same(item, Assert.Single(addUser.Value.Matches));
    }
        public LinkGenerationDecisionTree(IReadOnlyList <OutboundMatch> entries)
        {
            // We split up the entries into:
            // 1. attribute routes - these go into the tree
            // 2. conventional routes - these are a list
            var attributedEntries = new List <OutboundMatch>();

            _conventionalEntries = new List <OutboundMatch>();

            // Anything with a RoutePattern.RequiredValueAny as a RequiredValue is a conventional route.
            // This is because RequiredValueAny acts as a wildcard, whereas an attribute route entry
            // is denormalized to contain an exact set of required values.
            //
            // We will only see conventional routes show up here for endpoint routing.
            for (var i = 0; i < entries.Count; i++)
            {
                var isAttributeRoute = true;
                var entry            = entries[i];
                foreach (var kvp in entry.Entry.RequiredLinkValues)
                {
                    if (RoutePattern.IsRequiredValueAny(kvp.Value))
                    {
                        isAttributeRoute = false;
                        break;
                    }
                }

                if (isAttributeRoute)
                {
                    attributedEntries.Add(entry);
                }
                else
                {
                    _conventionalEntries.Add(entry);
                }
            }

            _root = DecisionTreeBuilder <OutboundMatch> .GenerateTree(
                attributedEntries,
                new OutboundMatchClassifier());
        }
예제 #8
0
        public LinkGenerationDecisionTree(IReadOnlyList <OutboundMatch> entries)
        {
            _root = DecisionTreeBuilder <OutboundMatch> .GenerateTree(
                entries,
                new OutboundMatchClassifier());

            _knownValues = new Dictionary <string, HashSet <object> >(StringComparer.OrdinalIgnoreCase);
            for (var i = 0; i < entries.Count; i++)
            {
                var entry = entries[i];
                foreach (var kvp in entry.Entry.RequiredLinkValues)
                {
                    if (!_knownValues.TryGetValue(kvp.Key, out var values))
                    {
                        values = new HashSet <object>(RouteValueEqualityComparer.Default);
                        _knownValues.Add(kvp.Key, values);
                    }

                    values.Add(kvp.Value ?? string.Empty);
                }
            }
        }
예제 #9
0
    public void BuildTree_WithDivergentCriteria()
    {
        // Arrange
        var items = new List <Item>();

        var item1 = new Item();

        item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy"));
        items.Add(item1);

        var item2 = new Item();

        item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout"));
        items.Add(item2);

        var item3 = new Item();

        item3.Criteria.Add("stub", new DecisionCriterionValue(value: "Bleh"));
        items.Add(item3);

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Matches);

        var action = tree.Criteria[0];

        Assert.Equal("action", action.Key);

        var stub = tree.Criteria[1];

        Assert.Equal("stub", stub.Key);
    }
예제 #10
0
    public void BuildTree_WithInteriorMatch()
    {
        // Arrange
        var items = new List <Item>();

        var item1 = new Item();

        item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy"));
        items.Add(item1);

        var item2 = new Item();

        item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store"));
        item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout"));
        items.Add(item2);

        var item3 = new Item();

        item3.Criteria.Add("action", new DecisionCriterionValue(value: "Buy"));
        items.Add(item3);

        // Act
        var tree = DecisionTreeBuilder <Item> .GenerateTree(items, new ItemClassifier());

        // Assert
        Assert.Empty(tree.Matches);

        var action = Assert.Single(tree.Criteria);

        Assert.Equal("action", action.Key);

        var buy = action.Branches["Buy"];

        Assert.Same(item3, Assert.Single(buy.Matches));
    }
예제 #11
0
 public LinkGenerationDecisionTree(IReadOnlyList <OutboundMatch> entries)
 {
     _root = DecisionTreeBuilder <OutboundMatch> .GenerateTree(
         entries,
         new OutboundMatchClassifier());
 }
예제 #12
0
 public LinkGenerationDecisionTree(IReadOnlyList <TreeRouteLinkGenerationEntry> entries)
 {
     _root = DecisionTreeBuilder <TreeRouteLinkGenerationEntry> .GenerateTree(
         entries,
         new AttributeRouteLinkGenerationEntryClassifier());
 }