Committed by
Gerrit Code Review
Merge "ONOS-22 - Add Constraints to CLI Commands"
Showing
10 changed files
with
122 additions
and
12 deletions
... | @@ -15,14 +15,16 @@ | ... | @@ -15,14 +15,16 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.cli.net; | 16 | package org.onlab.onos.cli.net; |
17 | 17 | ||
18 | +import java.util.List; | ||
19 | + | ||
18 | import org.apache.karaf.shell.commands.Argument; | 20 | import org.apache.karaf.shell.commands.Argument; |
19 | import org.apache.karaf.shell.commands.Command; | 21 | import org.apache.karaf.shell.commands.Command; |
20 | -import org.onlab.onos.cli.AbstractShellCommand; | ||
21 | import org.onlab.onos.net.HostId; | 22 | import org.onlab.onos.net.HostId; |
22 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 23 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
23 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 24 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
24 | import org.onlab.onos.net.flow.TrafficSelector; | 25 | import org.onlab.onos.net.flow.TrafficSelector; |
25 | import org.onlab.onos.net.flow.TrafficTreatment; | 26 | import org.onlab.onos.net.flow.TrafficTreatment; |
27 | +import org.onlab.onos.net.intent.Constraint; | ||
26 | import org.onlab.onos.net.intent.HostToHostIntent; | 28 | import org.onlab.onos.net.intent.HostToHostIntent; |
27 | import org.onlab.onos.net.intent.IntentService; | 29 | import org.onlab.onos.net.intent.IntentService; |
28 | 30 | ||
... | @@ -31,7 +33,7 @@ import org.onlab.onos.net.intent.IntentService; | ... | @@ -31,7 +33,7 @@ import org.onlab.onos.net.intent.IntentService; |
31 | */ | 33 | */ |
32 | @Command(scope = "onos", name = "add-host-intent", | 34 | @Command(scope = "onos", name = "add-host-intent", |
33 | description = "Installs host-to-host connectivity intent") | 35 | description = "Installs host-to-host connectivity intent") |
34 | -public class AddHostToHostIntentCommand extends AbstractShellCommand { | 36 | +public class AddHostToHostIntentCommand extends ConnectivityIntentCommand { |
35 | 37 | ||
36 | @Argument(index = 0, name = "one", description = "One host ID", | 38 | @Argument(index = 0, name = "one", description = "One host ID", |
37 | required = true, multiValued = false) | 39 | required = true, multiValued = false) |
... | @@ -50,9 +52,11 @@ public class AddHostToHostIntentCommand extends AbstractShellCommand { | ... | @@ -50,9 +52,11 @@ public class AddHostToHostIntentCommand extends AbstractShellCommand { |
50 | 52 | ||
51 | TrafficSelector selector = DefaultTrafficSelector.builder().build(); | 53 | TrafficSelector selector = DefaultTrafficSelector.builder().build(); |
52 | TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | 54 | TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); |
55 | + List<Constraint> constraints = buildConstraints(); | ||
53 | 56 | ||
54 | HostToHostIntent intent = new HostToHostIntent(appId(), oneId, twoId, | 57 | HostToHostIntent intent = new HostToHostIntent(appId(), oneId, twoId, |
55 | - selector, treatment); | 58 | + selector, treatment, |
59 | + constraints); | ||
56 | service.submit(intent); | 60 | service.submit(intent); |
57 | } | 61 | } |
58 | 62 | ... | ... |
... | @@ -23,11 +23,13 @@ import org.onlab.onos.net.PortNumber; | ... | @@ -23,11 +23,13 @@ import org.onlab.onos.net.PortNumber; |
23 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 23 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
24 | import org.onlab.onos.net.flow.TrafficSelector; | 24 | import org.onlab.onos.net.flow.TrafficSelector; |
25 | import org.onlab.onos.net.flow.TrafficTreatment; | 25 | import org.onlab.onos.net.flow.TrafficTreatment; |
26 | +import org.onlab.onos.net.intent.Constraint; | ||
26 | import org.onlab.onos.net.intent.Intent; | 27 | import org.onlab.onos.net.intent.Intent; |
27 | import org.onlab.onos.net.intent.IntentService; | 28 | import org.onlab.onos.net.intent.IntentService; |
28 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; | 29 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; |
29 | 30 | ||
30 | import java.util.HashSet; | 31 | import java.util.HashSet; |
32 | +import java.util.List; | ||
31 | import java.util.Set; | 33 | import java.util.Set; |
32 | 34 | ||
33 | import static org.onlab.onos.net.DeviceId.deviceId; | 35 | import static org.onlab.onos.net.DeviceId.deviceId; |
... | @@ -69,9 +71,11 @@ public class AddMultiPointToSinglePointIntentCommand extends ConnectivityIntentC | ... | @@ -69,9 +71,11 @@ public class AddMultiPointToSinglePointIntentCommand extends ConnectivityIntentC |
69 | 71 | ||
70 | TrafficSelector selector = buildTrafficSelector(); | 72 | TrafficSelector selector = buildTrafficSelector(); |
71 | TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | 73 | TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); |
74 | + List<Constraint> constraints = buildConstraints(); | ||
72 | 75 | ||
73 | Intent intent = new MultiPointToSinglePointIntent(appId(), selector, treatment, | 76 | Intent intent = new MultiPointToSinglePointIntent(appId(), selector, treatment, |
74 | - ingressPoints, egress); | 77 | + ingressPoints, egress, |
78 | + constraints); | ||
75 | service.submit(intent); | 79 | service.submit(intent); |
76 | } | 80 | } |
77 | 81 | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.cli.net; | 16 | package org.onlab.onos.cli.net; |
17 | 17 | ||
18 | +import java.util.List; | ||
19 | + | ||
18 | import org.apache.karaf.shell.commands.Argument; | 20 | import org.apache.karaf.shell.commands.Argument; |
19 | import org.apache.karaf.shell.commands.Command; | 21 | import org.apache.karaf.shell.commands.Command; |
20 | import org.onlab.onos.net.ConnectPoint; | 22 | import org.onlab.onos.net.ConnectPoint; |
... | @@ -22,6 +24,7 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -22,6 +24,7 @@ import org.onlab.onos.net.DeviceId; |
22 | import org.onlab.onos.net.PortNumber; | 24 | import org.onlab.onos.net.PortNumber; |
23 | import org.onlab.onos.net.flow.TrafficSelector; | 25 | import org.onlab.onos.net.flow.TrafficSelector; |
24 | import org.onlab.onos.net.flow.TrafficTreatment; | 26 | import org.onlab.onos.net.flow.TrafficTreatment; |
27 | +import org.onlab.onos.net.intent.Constraint; | ||
25 | import org.onlab.onos.net.intent.Intent; | 28 | import org.onlab.onos.net.intent.Intent; |
26 | import org.onlab.onos.net.intent.IntentService; | 29 | import org.onlab.onos.net.intent.IntentService; |
27 | import org.onlab.onos.net.intent.PointToPointIntent; | 30 | import org.onlab.onos.net.intent.PointToPointIntent; |
... | @@ -63,8 +66,10 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { | ... | @@ -63,8 +66,10 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { |
63 | TrafficSelector selector = buildTrafficSelector(); | 66 | TrafficSelector selector = buildTrafficSelector(); |
64 | TrafficTreatment treatment = builder().build(); | 67 | TrafficTreatment treatment = builder().build(); |
65 | 68 | ||
69 | + List<Constraint> constraints = buildConstraints(); | ||
70 | + | ||
66 | Intent intent = new PointToPointIntent(appId(), selector, treatment, | 71 | Intent intent = new PointToPointIntent(appId(), selector, treatment, |
67 | - ingress, egress); | 72 | + ingress, egress, constraints); |
68 | service.submit(intent); | 73 | service.submit(intent); |
69 | } | 74 | } |
70 | 75 | ... | ... |
... | @@ -15,14 +15,21 @@ | ... | @@ -15,14 +15,21 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.cli.net; | 16 | package org.onlab.onos.cli.net; |
17 | 17 | ||
18 | +import java.util.LinkedList; | ||
19 | +import java.util.List; | ||
20 | + | ||
18 | import org.apache.karaf.shell.commands.Option; | 21 | import org.apache.karaf.shell.commands.Option; |
19 | import org.onlab.onos.cli.AbstractShellCommand; | 22 | import org.onlab.onos.cli.AbstractShellCommand; |
20 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 23 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
21 | import org.onlab.onos.net.flow.TrafficSelector; | 24 | import org.onlab.onos.net.flow.TrafficSelector; |
25 | +import org.onlab.onos.net.intent.Constraint; | ||
26 | +import org.onlab.onos.net.intent.constraint.BandwidthConstraint; | ||
27 | +import org.onlab.onos.net.intent.constraint.LambdaConstraint; | ||
28 | +import org.onlab.onos.net.resource.Bandwidth; | ||
22 | import org.onlab.packet.Ethernet; | 29 | import org.onlab.packet.Ethernet; |
23 | import org.onlab.packet.MacAddress; | 30 | import org.onlab.packet.MacAddress; |
24 | 31 | ||
25 | -import com.google.common.base.Strings; | 32 | +import static com.google.common.base.Strings.isNullOrEmpty; |
26 | 33 | ||
27 | /** | 34 | /** |
28 | * Base class for command line operations for connectivity based intents. | 35 | * Base class for command line operations for connectivity based intents. |
... | @@ -41,6 +48,14 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { | ... | @@ -41,6 +48,14 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { |
41 | required = false, multiValued = false) | 48 | required = false, multiValued = false) |
42 | private String ethTypeString = ""; | 49 | private String ethTypeString = ""; |
43 | 50 | ||
51 | + @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth", | ||
52 | + required = false, multiValued = false) | ||
53 | + private String bandwidthString = ""; | ||
54 | + | ||
55 | + @Option(name = "-l", aliases = "--lambda", description = "Lambda", | ||
56 | + required = false, multiValued = false) | ||
57 | + private boolean lambda = false; | ||
58 | + | ||
44 | /** | 59 | /** |
45 | * Constructs a traffic selector based on the command line arguments | 60 | * Constructs a traffic selector based on the command line arguments |
46 | * presented to the command. | 61 | * presented to the command. |
... | @@ -50,21 +65,43 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { | ... | @@ -50,21 +65,43 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { |
50 | TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); | 65 | TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); |
51 | Short ethType = Ethernet.TYPE_IPV4; | 66 | Short ethType = Ethernet.TYPE_IPV4; |
52 | 67 | ||
53 | - if (!Strings.isNullOrEmpty(ethTypeString)) { | 68 | + if (!isNullOrEmpty(ethTypeString)) { |
54 | EthType ethTypeParameter = EthType.valueOf(ethTypeString); | 69 | EthType ethTypeParameter = EthType.valueOf(ethTypeString); |
55 | ethType = ethTypeParameter.value(); | 70 | ethType = ethTypeParameter.value(); |
56 | } | 71 | } |
57 | selectorBuilder.matchEthType(ethType); | 72 | selectorBuilder.matchEthType(ethType); |
58 | 73 | ||
59 | - if (!Strings.isNullOrEmpty(srcMacString)) { | 74 | + if (!isNullOrEmpty(srcMacString)) { |
60 | selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString)); | 75 | selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString)); |
61 | } | 76 | } |
62 | 77 | ||
63 | - if (!Strings.isNullOrEmpty(dstMacString)) { | 78 | + if (!isNullOrEmpty(dstMacString)) { |
64 | selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); | 79 | selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); |
65 | } | 80 | } |
66 | 81 | ||
67 | return selectorBuilder.build(); | 82 | return selectorBuilder.build(); |
68 | } | 83 | } |
69 | 84 | ||
85 | + /** | ||
86 | + * Builds the constraint list for this command based on the command line | ||
87 | + * parameters. | ||
88 | + * | ||
89 | + * @return List of constraint objects describing the constraints requested | ||
90 | + */ | ||
91 | + protected List<Constraint> buildConstraints() { | ||
92 | + final List<Constraint> constraints = new LinkedList<>(); | ||
93 | + | ||
94 | + // Check for a bandwidth specification | ||
95 | + if (!isNullOrEmpty(bandwidthString)) { | ||
96 | + final double bandwidthValue = Double.parseDouble(bandwidthString); | ||
97 | + constraints.add(new BandwidthConstraint(Bandwidth.valueOf(bandwidthValue))); | ||
98 | + } | ||
99 | + | ||
100 | + // Check for a lambda specification | ||
101 | + if (lambda) { | ||
102 | + constraints.add(new LambdaConstraint(null)); | ||
103 | + } | ||
104 | + | ||
105 | + return constraints; | ||
106 | + } | ||
70 | } | 107 | } | ... | ... |
... | @@ -105,6 +105,7 @@ public final class HostToHostIntent extends ConnectivityIntent { | ... | @@ -105,6 +105,7 @@ public final class HostToHostIntent extends ConnectivityIntent { |
105 | .add("appId", appId()) | 105 | .add("appId", appId()) |
106 | .add("selector", selector()) | 106 | .add("selector", selector()) |
107 | .add("treatment", treatment()) | 107 | .add("treatment", treatment()) |
108 | + .add("constraints", constraints()) | ||
108 | .add("one", one) | 109 | .add("one", one) |
109 | .add("two", two) | 110 | .add("two", two) |
110 | .toString(); | 111 | .toString(); | ... | ... |
... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint; | ... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint; |
22 | import org.onlab.onos.net.flow.TrafficSelector; | 22 | import org.onlab.onos.net.flow.TrafficSelector; |
23 | import org.onlab.onos.net.flow.TrafficTreatment; | 23 | import org.onlab.onos.net.flow.TrafficTreatment; |
24 | 24 | ||
25 | +import java.util.List; | ||
25 | import java.util.Set; | 26 | import java.util.Set; |
26 | 27 | ||
27 | import static com.google.common.base.Preconditions.checkArgument; | 28 | import static com.google.common.base.Preconditions.checkArgument; |
... | @@ -65,6 +66,38 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { | ... | @@ -65,6 +66,38 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { |
65 | } | 66 | } |
66 | 67 | ||
67 | /** | 68 | /** |
69 | + * Creates a new multi-to-single point connectivity intent for the specified | ||
70 | + * traffic selector and treatment. | ||
71 | + * | ||
72 | + * @param appId application identifier | ||
73 | + * @param selector traffic selector | ||
74 | + * @param treatment treatment | ||
75 | + * @param ingressPoints set of ports from which ingress traffic originates | ||
76 | + * @param egressPoint port to which traffic will egress | ||
77 | + * @param constraints constraints to apply to the intent | ||
78 | + * @throws NullPointerException if {@code ingressPoints} or | ||
79 | + * {@code egressPoint} is null. | ||
80 | + * @throws IllegalArgumentException if the size of {@code ingressPoints} is | ||
81 | + * not more than 1 | ||
82 | + */ | ||
83 | + public MultiPointToSinglePointIntent(ApplicationId appId, | ||
84 | + TrafficSelector selector, | ||
85 | + TrafficTreatment treatment, | ||
86 | + Set<ConnectPoint> ingressPoints, | ||
87 | + ConnectPoint egressPoint, | ||
88 | + List<Constraint> constraints) { | ||
89 | + super(id(MultiPointToSinglePointIntent.class, selector, treatment, | ||
90 | + ingressPoints, egressPoint), appId, null, selector, treatment, | ||
91 | + constraints); | ||
92 | + | ||
93 | + checkNotNull(ingressPoints); | ||
94 | + checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty"); | ||
95 | + | ||
96 | + this.ingressPoints = Sets.newHashSet(ingressPoints); | ||
97 | + this.egressPoint = checkNotNull(egressPoint); | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
68 | * Constructor for serializer. | 101 | * Constructor for serializer. |
69 | */ | 102 | */ |
70 | protected MultiPointToSinglePointIntent() { | 103 | protected MultiPointToSinglePointIntent() { |
... | @@ -101,6 +134,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { | ... | @@ -101,6 +134,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { |
101 | .add("treatment", treatment()) | 134 | .add("treatment", treatment()) |
102 | .add("ingress", ingressPoints()) | 135 | .add("ingress", ingressPoints()) |
103 | .add("egress", egressPoint()) | 136 | .add("egress", egressPoint()) |
137 | + .add("constraints", constraints()) | ||
104 | .toString(); | 138 | .toString(); |
105 | } | 139 | } |
106 | } | 140 | } | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | +import java.util.List; | ||
19 | + | ||
18 | import com.google.common.base.MoreObjects; | 20 | import com.google.common.base.MoreObjects; |
19 | import org.onlab.onos.core.ApplicationId; | 21 | import org.onlab.onos.core.ApplicationId; |
20 | import org.onlab.onos.net.Path; | 22 | import org.onlab.onos.net.Path; |
... | @@ -46,6 +48,24 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -46,6 +48,24 @@ public class PathIntent extends ConnectivityIntent { |
46 | } | 48 | } |
47 | 49 | ||
48 | /** | 50 | /** |
51 | + * Creates a new point-to-point intent with the supplied ingress/egress | ||
52 | + * ports and using the specified explicit path. | ||
53 | + * | ||
54 | + * @param appId application identifier | ||
55 | + * @param selector traffic selector | ||
56 | + * @param treatment treatment | ||
57 | + * @param path traversed links | ||
58 | + * @param constraints optional list of constraints | ||
59 | + * @throws NullPointerException {@code path} is null | ||
60 | + */ | ||
61 | + public PathIntent(ApplicationId appId, TrafficSelector selector, | ||
62 | + TrafficTreatment treatment, Path path, List<Constraint> constraints) { | ||
63 | + super(id(PathIntent.class, selector, treatment, path, constraints), appId, | ||
64 | + resources(path.links()), selector, treatment, constraints); | ||
65 | + this.path = path; | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
49 | * Constructor for serializer. | 69 | * Constructor for serializer. |
50 | */ | 70 | */ |
51 | protected PathIntent() { | 71 | protected PathIntent() { |
... | @@ -75,6 +95,7 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -75,6 +95,7 @@ public class PathIntent extends ConnectivityIntent { |
75 | .add("appId", appId()) | 95 | .add("appId", appId()) |
76 | .add("selector", selector()) | 96 | .add("selector", selector()) |
77 | .add("treatment", treatment()) | 97 | .add("treatment", treatment()) |
98 | + .add("constraints", constraints()) | ||
78 | .add("path", path) | 99 | .add("path", path) |
79 | .toString(); | 100 | .toString(); |
80 | } | 101 | } | ... | ... |
... | @@ -118,13 +118,14 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> | ... | @@ -118,13 +118,14 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> |
118 | 118 | ||
119 | @Override | 119 | @Override |
120 | public double weight(TopologyEdge edge) { | 120 | public double weight(TopologyEdge edge) { |
121 | - if (constraints == null) { | 121 | + if (constraints == null || !constraints.iterator().hasNext()) { |
122 | return 1.0; | 122 | return 1.0; |
123 | } | 123 | } |
124 | 124 | ||
125 | // iterate over all constraints in order and return the weight of | 125 | // iterate over all constraints in order and return the weight of |
126 | // the first one with fast fail over the first failure | 126 | // the first one with fast fail over the first failure |
127 | Iterator<Constraint> it = constraints.iterator(); | 127 | Iterator<Constraint> it = constraints.iterator(); |
128 | + | ||
128 | double cost = it.next().cost(edge.link(), resourceService); | 129 | double cost = it.next().cost(edge.link(), resourceService); |
129 | while (it.hasNext() && cost > 0) { | 130 | while (it.hasNext() && cost > 0) { |
130 | if (it.next().cost(edge.link(), resourceService) < 0) { | 131 | if (it.next().cost(edge.link(), resourceService) < 0) { |
... | @@ -132,6 +133,7 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> | ... | @@ -132,6 +133,7 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> |
132 | } | 133 | } |
133 | } | 134 | } |
134 | return cost; | 135 | return cost; |
136 | + | ||
135 | } | 137 | } |
136 | } | 138 | } |
137 | 139 | ... | ... |
... | @@ -70,7 +70,8 @@ public class HostToHostIntentCompiler | ... | @@ -70,7 +70,8 @@ public class HostToHostIntentCompiler |
70 | HostToHostIntent intent) { | 70 | HostToHostIntent intent) { |
71 | TrafficSelector selector = builder(intent.selector()) | 71 | TrafficSelector selector = builder(intent.selector()) |
72 | .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build(); | 72 | .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build(); |
73 | - return new PathIntent(intent.appId(), selector, intent.treatment(), path); | 73 | + return new PathIntent(intent.appId(), selector, intent.treatment(), |
74 | + path, intent.constraints()); | ||
74 | } | 75 | } |
75 | 76 | ||
76 | } | 77 | } | ... | ... |
... | @@ -77,7 +77,8 @@ public class PointToPointIntentCompiler | ... | @@ -77,7 +77,8 @@ public class PointToPointIntentCompiler |
77 | private Intent createPathIntent(Path path, | 77 | private Intent createPathIntent(Path path, |
78 | PointToPointIntent intent) { | 78 | PointToPointIntent intent) { |
79 | return new PathIntent(intent.appId(), | 79 | return new PathIntent(intent.appId(), |
80 | - intent.selector(), intent.treatment(), path); | 80 | + intent.selector(), intent.treatment(), path, |
81 | + intent.constraints()); | ||
81 | } | 82 | } |
82 | 83 | ||
83 | } | 84 | } | ... | ... |
-
Please register or login to post a comment