5746003c19f75b3432c2235d04ed94c97a703286
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onosproject.codec.impl;
17
18 import java.time.Duration;
19 import java.util.ArrayList;
20 import java.util.stream.IntStream;
21
22 import org.onlab.util.Bandwidth;
23 import org.onosproject.net.DeviceId;
24 import org.onosproject.net.IndexedLambda;
25 import org.onosproject.net.Link;
26 import org.onosproject.net.intent.Constraint;
27 import org.onosproject.net.intent.constraint.AnnotationConstraint;
28 import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
29 import org.onosproject.net.intent.constraint.BandwidthConstraint;
30 import org.onosproject.net.intent.constraint.LambdaConstraint;
31 import org.onosproject.net.intent.constraint.LatencyConstraint;
32 import org.onosproject.net.intent.constraint.LinkTypeConstraint;
33 import org.onosproject.net.intent.constraint.ObstacleConstraint;
34 import org.onosproject.net.intent.constraint.WaypointConstraint;
35 import org.onosproject.net.resource.link.BandwidthResource;
36 import org.onosproject.net.resource.link.LambdaResource;
37
38 import com.fasterxml.jackson.databind.JsonNode;
39 import com.fasterxml.jackson.databind.node.ObjectNode;
40
41 import static org.onlab.util.Tools.nullIsIllegal;
42
43 /**
44  * Constraint JSON decoder.
45  */
46 public final class DecodeConstraintCodecHelper {
47     private final ObjectNode json;
48
49     /**
50      * Constructs a constraint decoder.
51      *
52      * @param json object node to decode
53      */
54     public DecodeConstraintCodecHelper(ObjectNode json) {
55         this.json = json;
56     }
57
58     /**
59      * Decodes a link type constraint.
60      *
61      * @return link type constraint object.
62      */
63     private Constraint decodeLinkTypeConstraint() {
64         boolean inclusive = nullIsIllegal(json.get(ConstraintCodec.INCLUSIVE),
65                 ConstraintCodec.INCLUSIVE + ConstraintCodec.MISSING_MEMBER_MESSAGE).asBoolean();
66
67         JsonNode types = nullIsIllegal(json.get(ConstraintCodec.TYPES),
68                 ConstraintCodec.TYPES + ConstraintCodec.MISSING_MEMBER_MESSAGE);
69         if (types.size() < 1) {
70             throw new IllegalArgumentException(
71                     "types array in link constraint must have at least one value");
72         }
73
74         ArrayList<Link.Type> typesEntries = new ArrayList<>(types.size());
75         IntStream.range(0, types.size())
76                 .forEach(index ->
77                         typesEntries.add(Link.Type.valueOf(types.get(index).asText())));
78
79         return new LinkTypeConstraint(inclusive,
80                 typesEntries.toArray(new Link.Type[types.size()]));
81     }
82
83     /**
84      * Decodes an annotation constraint.
85      *
86      * @return annotation constraint object.
87      */
88     private Constraint decodeAnnotationConstraint() {
89         String key = nullIsIllegal(json.get(ConstraintCodec.KEY),
90                 ConstraintCodec.KEY + ConstraintCodec.MISSING_MEMBER_MESSAGE)
91                 .asText();
92         double threshold = nullIsIllegal(json.get(ConstraintCodec.THRESHOLD),
93                 ConstraintCodec.THRESHOLD + ConstraintCodec.MISSING_MEMBER_MESSAGE)
94                 .asDouble();
95
96         return new AnnotationConstraint(key, threshold);
97     }
98
99     /**
100      * Decodes a lambda constraint.
101      *
102      * @return lambda constraint object.
103      */
104     private Constraint decodeLambdaConstraint() {
105         long lambda = nullIsIllegal(json.get(ConstraintCodec.LAMBDA),
106                 ConstraintCodec.LAMBDA + ConstraintCodec.MISSING_MEMBER_MESSAGE)
107                 .asLong();
108
109         return new LambdaConstraint(LambdaResource.valueOf(new IndexedLambda(lambda)));
110     }
111
112     /**
113      * Decodes a latency constraint.
114      *
115      * @return latency constraint object.
116      */
117     private Constraint decodeLatencyConstraint() {
118         long latencyMillis = nullIsIllegal(json.get(ConstraintCodec.LATENCY_MILLIS),
119                 ConstraintCodec.LATENCY_MILLIS + ConstraintCodec.MISSING_MEMBER_MESSAGE)
120                 .asLong();
121
122         return new LatencyConstraint(Duration.ofMillis(latencyMillis));
123     }
124
125     /**
126      * Decodes an obstacle constraint.
127      *
128      * @return obstacle constraint object.
129      */
130     private Constraint decodeObstacleConstraint() {
131         JsonNode obstacles = nullIsIllegal(json.get(ConstraintCodec.OBSTACLES),
132                 ConstraintCodec.OBSTACLES + ConstraintCodec.MISSING_MEMBER_MESSAGE);
133         if (obstacles.size() < 1) {
134             throw new IllegalArgumentException(
135                     "obstacles array in obstacles constraint must have at least one value");
136         }
137
138         ArrayList<DeviceId> obstacleEntries = new ArrayList<>(obstacles.size());
139         IntStream.range(0, obstacles.size())
140                 .forEach(index ->
141                         obstacleEntries.add(DeviceId.deviceId(obstacles.get(index).asText())));
142
143         return new ObstacleConstraint(
144                 obstacleEntries.toArray(new DeviceId[obstacles.size()]));
145     }
146
147     /**
148      * Decodes a waypoint constraint.
149      *
150      * @return waypoint constraint object.
151      */
152     private Constraint decodeWaypointConstraint() {
153         JsonNode waypoints = nullIsIllegal(json.get(ConstraintCodec.WAYPOINTS),
154                 ConstraintCodec.WAYPOINTS + ConstraintCodec.MISSING_MEMBER_MESSAGE);
155         if (waypoints.size() < 1) {
156             throw new IllegalArgumentException(
157                     "obstacles array in obstacles constraint must have at least one value");
158         }
159
160         ArrayList<DeviceId> waypointEntries = new ArrayList<>(waypoints.size());
161         IntStream.range(0, waypoints.size())
162                 .forEach(index ->
163                         waypointEntries.add(DeviceId.deviceId(waypoints.get(index).asText())));
164
165         return new WaypointConstraint(
166                 waypointEntries.toArray(new DeviceId[waypoints.size()]));
167     }
168
169     /**
170      * Decodes an asymmetric path constraint.
171      *
172      * @return asymmetric path constraint object.
173      */
174     private Constraint decodeAsymmetricPathConstraint() {
175         return new AsymmetricPathConstraint();
176     }
177
178     /**
179      * Decodes a bandwidth constraint.
180      *
181      * @return bandwidth constraint object.
182      */
183     private Constraint decodeBandwidthConstraint() {
184         double bandwidth = nullIsIllegal(json.get(ConstraintCodec.BANDWIDTH),
185                 ConstraintCodec.BANDWIDTH + ConstraintCodec.MISSING_MEMBER_MESSAGE)
186                 .asDouble();
187
188         return new BandwidthConstraint(new BandwidthResource(Bandwidth.bps(bandwidth)));
189     }
190
191     /**
192      * Decodes the given constraint.
193      *
194      * @return constraint object.
195      */
196     public Constraint decode() {
197         final String type = nullIsIllegal(json.get(ConstraintCodec.TYPE),
198                 ConstraintCodec.TYPE + ConstraintCodec.MISSING_MEMBER_MESSAGE)
199                 .asText();
200
201         if (type.equals(BandwidthConstraint.class.getSimpleName())) {
202             return decodeBandwidthConstraint();
203         } else if (type.equals(LambdaConstraint.class.getSimpleName())) {
204             return decodeLambdaConstraint();
205         } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) {
206             return decodeLinkTypeConstraint();
207         } else if (type.equals(AnnotationConstraint.class.getSimpleName())) {
208             return decodeAnnotationConstraint();
209         } else if (type.equals(LatencyConstraint.class.getSimpleName())) {
210             return decodeLatencyConstraint();
211         } else if (type.equals(ObstacleConstraint.class.getSimpleName())) {
212             return decodeObstacleConstraint();
213         } else if (type.equals(WaypointConstraint.class.getSimpleName())) {
214             return decodeWaypointConstraint();
215         } else if (type.equals(AsymmetricPathConstraint.class.getSimpleName())) {
216             return decodeAsymmetricPathConstraint();
217         } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) {
218             return decodeLinkTypeConstraint();
219         } else if (type.equals(AnnotationConstraint.class.getSimpleName())) {
220             return decodeAnnotationConstraint();
221         }
222         throw new IllegalArgumentException("Instruction type "
223                 + type + " is not supported");
224     }
225 }