blob: d07e516906d36dd15a8f0af56a560c00ce36ba91 [file] [log] [blame]
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -07001/*
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -08002 * Copyright 2015-2016 Open Networking Laboratory
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -07003 *
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 */
16package org.onosproject.net.newresource;
17
18import com.google.common.annotations.Beta;
19import com.google.common.base.MoreObjects;
20import com.google.common.collect.ImmutableList;
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080021import org.onosproject.net.DeviceId;
22import org.onosproject.net.PortNumber;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070023
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070024import java.util.List;
25import java.util.Objects;
26import java.util.Optional;
27
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080028import static com.google.common.base.Preconditions.checkArgument;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070029import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080030import static com.google.common.base.Preconditions.checkState;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070031
32/**
33 * An object that is used to locate a resource in a network.
34 * A ResourcePath represents a path that is hierarchical and composed of a sequence
35 * of elementary resources that are not globally identifiable. A ResourcePath can be a globally
36 * unique resource identifier.
37 *
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080038 * Two types of resource are considered. One is discrete type and the other is continuous type.
39 * Discrete type resource is a resource whose amount is measured as a discrete unit. VLAN ID and
40 * MPLS label are examples of discrete type resource. Continuous type resource is a resource whose
41 * amount is measured as a continuous value. Bandwidth is an example of continuous type resource.
42 * A double value is associated with a continuous type value.
43 *
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070044 * Users of this class must keep the semantics of resources regarding the hierarchical structure.
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080045 * For example, resource path, Device:1/Port:1/VLAN ID:100, is valid, but resource path,
46 * VLAN ID:100/Device:1/Port:1 is not valid because a link is not a sub-component of a VLAN ID.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070047 */
48@Beta
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080049public abstract class ResourcePath {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070050
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080051 private final Discrete parent;
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -080052 private final Key key;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070053
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080054 public static final Discrete ROOT = new Discrete();
Sho SHIMIZUba41fc12015-08-12 15:43:22 -070055
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080056 public static ResourcePath discrete(DeviceId device) {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -080057 return new Discrete(Key.of(device));
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080058 }
59
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070060 /**
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080061 * Creates an resource path which represents a discrete-type resource from the specified components.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070062 *
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080063 * @param device device ID which is the first component of the path
64 * @param components following components of the path. The order represents hierarchical structure of the resource.
Sho SHIMIZUe5524562015-11-24 14:41:20 -080065 * @return resource path instance
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070066 */
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080067 public static ResourcePath discrete(DeviceId device, Object... components) {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -080068 return new Discrete(Key.of(device, components));
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080069 }
70
71 /**
72 * Creates an resource path which represents a discrete-type resource from the specified components.
73 *
74 * @param device device ID which is the first component of the path
75 * @param port port number which is the second component of the path
76 * @param components following components of the path. The order represents hierarchical structure of the resource.
77 * @return resource path instance
78 */
79 public static ResourcePath discrete(DeviceId device, PortNumber port, Object... components) {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -080080 return new Discrete(Key.of(device, port, components));
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080081 }
82
83 /**
84 * Creates an resource path which represents a continuous-type resource from the specified components.
85 *
86 * @param value amount of the resource
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080087 * @param device device ID which is the first component of the path
88 * @param components following components of the path. The order represents hierarchical structure of the resource.
Sho SHIMIZUe5524562015-11-24 14:41:20 -080089 * @return resource path instance
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080090 */
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080091 public static ResourcePath continuous(double value, DeviceId device, Object... components) {
92 checkArgument(components.length > 0,
93 "Length of components must be greater thant 0, but " + components.length);
94
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -080095 return new Continuous(Key.of(device, components), value);
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080096 }
97
98 /**
99 * Creates an resource path which represents a continuous-type resource from the specified components.
100 *
101 * @param value amount of the resource
102 * @param device device ID which is the first component of the path.
103 * @param port port number which is the second component of the path.
104 * @param components following components of the path. The order represents hierarchical structure of the resource.
105 * @return resource path instance
106 */
107 public static ResourcePath continuous(double value, DeviceId device, PortNumber port, Object... components) {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800108 return new Continuous(Key.of(device, port, components), value);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700109 }
110
111 /**
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800112 * Creates an resource path from the specified key.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700113 *
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800114 * @param key key of the path
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700115 */
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800116 protected ResourcePath(Key key) {
117 checkNotNull(key);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700118
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800119 this.key = key;
120 if (key.components.size() == 1) {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800121 this.parent = ROOT;
122 } else {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800123 this.parent = new Discrete(key.parent());
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800124 }
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800125 }
126
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700127 // for serialization
128 private ResourcePath() {
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800129 this.parent = null;
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800130 this.key = Key.ROOT;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700131 }
132
133 /**
134 * Returns the components of this resource path.
135 *
136 * @return the components of this resource path
137 */
138 public List<Object> components() {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800139 return key.components;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700140 }
141
142 /**
143 * Returns the parent resource path of this instance.
144 * E.g. if this path is Link:1/VLAN ID:100, the return value is the resource path for Link:1.
145 *
146 * @return the parent resource path of this instance.
147 * If there is no parent, empty instance will be returned.
148 */
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800149 public Optional<Discrete> parent() {
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800150 return Optional.ofNullable(parent);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700151 }
152
Sho SHIMIZU9e1e9de2015-11-25 15:48:48 -0800153 /**
154 * Returns a child resource path of this instance with specifying the child object.
155 * The child resource path is discrete-type.
156 *
157 * @param child child object
158 * @return a child resource path
159 */
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800160 public ResourcePath child(Object child) {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800161 checkState(this instanceof Discrete);
162
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800163 return new Discrete(key().child(child));
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800164 }
165
Sho SHIMIZU9e1e9de2015-11-25 15:48:48 -0800166 /**
167 * Returns a child resource path of this instance with specifying a child object and
168 * value. The child resource path is continuous-type.
169 *
170 * @param child child object
171 * @param value value
172 * @return a child resource path
173 */
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800174 public ResourcePath child(Object child, double value) {
175 checkState(this instanceof Discrete);
176
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800177 return new Continuous(key.child(child), value);
Sho SHIMIZU01120782015-08-21 15:48:43 -0700178 }
179
180 /**
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700181 * Returns the last component of this instance.
182 *
183 * @return the last component of this instance.
184 * The return value is equal to the last object of {@code components()}.
185 */
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800186 public Object last() {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800187 if (key.components.isEmpty()) {
188 return null;
189 }
190 return key.components.get(key.components.size() - 1);
191 }
192
193 /**
194 * Returns the key of this resource path.
195 *
196 * @return the key of this resource path
197 */
198 public Key key() {
199 return key;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700200 }
201
202 @Override
203 public int hashCode() {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800204 return key.hashCode();
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700205 }
206
207 @Override
208 public boolean equals(Object obj) {
209 if (this == obj) {
210 return true;
211 }
212 if (!(obj instanceof ResourcePath)) {
213 return false;
214 }
215 final ResourcePath that = (ResourcePath) obj;
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800216 return Objects.equals(this.key, that.key);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700217 }
218
219 @Override
220 public String toString() {
221 return MoreObjects.toStringHelper(this)
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800222 .add("key", key)
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700223 .toString();
224 }
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800225
226 /**
227 * Represents a resource path which specifies a resource which can be measured
228 * as a discrete unit. A VLAN ID and a MPLS label of a link are examples of the resource.
229 * <p>
230 * Note: This class is exposed to the public, but intended to be used in the resource API
231 * implementation only. It is not for resource API user.
232 * </p>
233 */
Sho SHIMIZU6196cae2015-11-25 12:02:12 -0800234 @Beta
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800235 public static final class Discrete extends ResourcePath {
236 private Discrete() {
237 super();
238 }
239
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800240 private Discrete(Key key) {
241 super(key);
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800242 }
243 }
244
245 /**
246 * Represents a resource path which specifies a resource which can be measured
247 * as continuous value. Bandwidth of a link is an example of the resource.
248 * <p>
249 * Note: This class is exposed to the public, but intended to be used in the resource API
250 * implementation only. It is not for resource API user.
251 */
Sho SHIMIZU6196cae2015-11-25 12:02:12 -0800252 @Beta
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800253 public static final class Continuous extends ResourcePath {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800254 private final double value;
255
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800256 private Continuous(Key key, double value) {
257 super(key);
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800258 this.value = value;
259 }
260
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800261 @Override
262 public int hashCode() {
263 return Objects.hash(this.key(), this.value);
264 }
265
266 @Override
267 public boolean equals(Object obj) {
268 if (this == obj) {
269 return true;
270 }
271
272 if (!(obj instanceof Continuous)) {
273 return false;
274 }
275
276 if (!super.equals(obj)) {
277 return false;
278 }
279
280 final Continuous other = (Continuous) obj;
281 return Objects.equals(this.key(), other.key());
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800282 }
283
284 /**
285 * Returns the value of the resource amount.
286 *
287 * @return the value of the resource amount
288 */
289 public double value() {
290 return value;
291 }
292 }
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800293
294 /**
295 * Represents key of resource path used as a key in ResourceStore.
296 * This class is exposed to public, but intended to use only in ResourceStore implementations.
297 */
298 @Beta
299 public static final class Key {
300 private static final Key ROOT = new Key();
301
302 private final ImmutableList<Object> components;
303
304 private static Key of(DeviceId device, Object... components) {
305 return new Key(ImmutableList.builder()
306 .add(device)
307 .add(components)
308 .build());
309 }
310
311 private static Key of(DeviceId device, PortNumber port, Object... components) {
312 return new Key(ImmutableList.builder()
313 .add(device)
314 .add(port)
315 .add(components)
316 .build());
317 }
318
319 private Key(ImmutableList<Object> components) {
320 this.components = checkNotNull(components);
321 }
322
323 // for serializer
324 private Key() {
325 this.components = ImmutableList.of();
326 }
327
328 // IndexOutOfBoundsException is raised when the instance is equal to ROOT
329 private Key parent() {
330 if (components.size() == 1) {
331 return ROOT;
332 } else {
333 return new Key(components.subList(0, components.size() - 1));
334 }
335 }
336
337 private Key child(Object child) {
338 return new Key(ImmutableList.builder()
339 .add(components)
340 .add(child)
341 .build());
342 }
343
344 @Override
345 public int hashCode() {
346 return components.hashCode();
347 }
348
349 @Override
350 public boolean equals(Object obj) {
351 if (this == obj) {
352 return true;
353 }
354 if (!(obj instanceof Key)) {
355 return false;
356 }
357
358 Key other = (Key) obj;
359 return Objects.equals(this.components, other.components);
360 }
361
362 @Override
363 public String toString() {
364 return MoreObjects.toStringHelper(this)
365 .add("components", components)
366 .toString();
367 }
368 }
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700369}