blob: 1b05d945df9cbc66790bbb9da5a8c5c95bc13eb1 [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;
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080020import org.onosproject.net.DeviceId;
21import org.onosproject.net.PortNumber;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070022
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070023import java.util.List;
24import java.util.Objects;
25import java.util.Optional;
26
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080027import static com.google.common.base.Preconditions.checkArgument;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070028import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080029import static com.google.common.base.Preconditions.checkState;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070030
31/**
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080032 * An object that represent a resource in a network.
33 * A Resource can represents path-like hierarchical structure with its ID. An ID of resource is
34 * composed of a sequence of elementary resources that are not globally identifiable. A Resource
35 * can be globally identifiable by its ID.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070036 *
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080037 * Two types of resource are considered. One is discrete type and the other is continuous type.
38 * Discrete type resource is a resource whose amount is measured as a discrete unit. VLAN ID and
39 * MPLS label are examples of discrete type resource. Continuous type resource is a resource whose
40 * amount is measured as a continuous value. Bandwidth is an example of continuous type resource.
41 * A double value is associated with a continuous type value.
42 *
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070043 * Users of this class must keep the semantics of resources regarding the hierarchical structure.
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080044 * For example, resource, Device:1/Port:1/VLAN ID:100, is valid, but resource,
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080045 * 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 -070046 */
47@Beta
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080048public abstract class Resource {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070049
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080050 private final Discrete parent;
Sho SHIMIZU76b30f72016-01-11 14:08:35 -080051 private final ResourceId id;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070052
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080053 public static final Discrete ROOT = new Discrete();
Sho SHIMIZUba41fc12015-08-12 15:43:22 -070054
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080055 public static Resource discrete(DeviceId device) {
Sho SHIMIZU2d310222016-01-22 11:45:11 -080056 return new Discrete(ResourceId.discrete(device));
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080057 }
58
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070059 /**
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080060 * Creates an resource path which represents a discrete-type resource from the specified components.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070061 *
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080062 * @param device device ID which is the first component of the path
63 * @param components following components of the path. The order represents hierarchical structure of the resource.
Sho SHIMIZUe5524562015-11-24 14:41:20 -080064 * @return resource path instance
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070065 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080066 public static Resource discrete(DeviceId device, Object... components) {
Sho SHIMIZU2d310222016-01-22 11:45:11 -080067 return new Discrete(ResourceId.discrete(device, components));
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080068 }
69
70 /**
71 * Creates an resource path which represents a discrete-type resource from the specified components.
72 *
73 * @param device device ID which is the first component of the path
74 * @param port port number which is the second component of the path
75 * @param components following components of the path. The order represents hierarchical structure of the resource.
76 * @return resource path instance
77 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080078 public static Resource discrete(DeviceId device, PortNumber port, Object... components) {
Sho SHIMIZU2d310222016-01-22 11:45:11 -080079 return new Discrete(ResourceId.discrete(device, port, components));
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080080 }
81
82 /**
83 * Creates an resource path which represents a continuous-type resource from the specified components.
84 *
85 * @param value amount of the resource
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080086 * @param device device ID which is the first component of the path
87 * @param components following components of the path. The order represents hierarchical structure of the resource.
Sho SHIMIZU2d310222016-01-22 11:45:11 -080088 * The last element of this list must be an {@link Class} instance. Otherwise, this method throws
89 * an IllegalArgumentException.
Sho SHIMIZUe5524562015-11-24 14:41:20 -080090 * @return resource path instance
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -080091 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -080092 public static Resource continuous(double value, DeviceId device, Object... components) {
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080093 checkArgument(components.length > 0,
94 "Length of components must be greater thant 0, but " + components.length);
95
Sho SHIMIZU2d310222016-01-22 11:45:11 -080096 return new Continuous(ResourceId.continuous(device, components), value);
Sho SHIMIZUb1f16252015-11-25 23:03:16 -080097 }
98
99 /**
100 * Creates an resource path which represents a continuous-type resource from the specified components.
101 *
102 * @param value amount of the resource
103 * @param device device ID which is the first component of the path.
104 * @param port port number which is the second component of the path.
105 * @param components following components of the path. The order represents hierarchical structure of the resource.
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800106 * The last element of this list must be an {@link Class} instance. Otherwise, this method throws
107 * an IllegalArgumentException.
Sho SHIMIZUb1f16252015-11-25 23:03:16 -0800108 * @return resource path instance
109 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800110 public static Resource continuous(double value, DeviceId device, PortNumber port, Object... components) {
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800111 return new Continuous(ResourceId.continuous(device, port, components), value);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700112 }
113
114 /**
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800115 * Creates an resource path from the specified id.
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700116 *
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800117 * @param id id of the path
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700118 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800119 protected Resource(ResourceId id) {
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800120 checkNotNull(id);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700121
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800122 this.id = id;
123 if (id.components.size() == 1) {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800124 this.parent = ROOT;
125 } else {
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800126 this.parent = new Discrete(id.parent());
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800127 }
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800128 }
129
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700130 // for serialization
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800131 private Resource() {
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800132 this.parent = null;
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800133 this.id = ResourceId.ROOT;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700134 }
135
136 /**
137 * Returns the components of this resource path.
138 *
139 * @return the components of this resource path
140 */
141 public List<Object> components() {
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800142 return id.components;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700143 }
144
145 /**
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800146 * Returns the volume of this resource.
147 *
148 * @return the volume of this resource
149 */
150 // TODO: think about other naming possibilities. amount? quantity?
151 public abstract <T> T volume();
152
153 /**
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700154 * Returns the parent resource path of this instance.
155 * E.g. if this path is Link:1/VLAN ID:100, the return value is the resource path for Link:1.
156 *
157 * @return the parent resource path of this instance.
158 * If there is no parent, empty instance will be returned.
159 */
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800160 public Optional<Discrete> parent() {
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800161 return Optional.ofNullable(parent);
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700162 }
163
Sho SHIMIZU9e1e9de2015-11-25 15:48:48 -0800164 /**
165 * Returns a child resource path of this instance with specifying the child object.
166 * The child resource path is discrete-type.
167 *
168 * @param child child object
169 * @return a child resource path
170 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800171 public Resource child(Object child) {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800172 checkState(this instanceof Discrete);
173
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800174 return new Discrete(id().child(child));
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800175 }
176
Sho SHIMIZU9e1e9de2015-11-25 15:48:48 -0800177 /**
178 * Returns a child resource path of this instance with specifying a child object and
179 * value. The child resource path is continuous-type.
180 *
181 * @param child child object
182 * @param value value
183 * @return a child resource path
184 */
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800185 public Resource child(Object child, double value) {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800186 checkState(this instanceof Discrete);
187
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800188 return new Continuous(id.child(child), value);
Sho SHIMIZU01120782015-08-21 15:48:43 -0700189 }
190
191 /**
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700192 * Returns the last component of this instance.
193 *
194 * @return the last component of this instance.
195 * The return value is equal to the last object of {@code components()}.
196 */
Sho SHIMIZUc9546a32015-11-10 11:22:28 -0800197 public Object last() {
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800198 if (id.components.isEmpty()) {
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800199 return null;
200 }
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800201 return id.components.get(id.components.size() - 1);
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800202 }
203
204 /**
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800205 * Returns the ID of this resource path.
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800206 *
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800207 * @return the ID of this resource path
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800208 */
Sho SHIMIZU76b30f72016-01-11 14:08:35 -0800209 public ResourceId id() {
210 return id;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700211 }
212
213 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700214 public String toString() {
215 return MoreObjects.toStringHelper(this)
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800216 .add("id", id())
217 .add("volume", volume())
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700218 .toString();
219 }
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800220
221 /**
222 * Represents a resource path which specifies a resource which can be measured
223 * as a discrete unit. A VLAN ID and a MPLS label of a link are examples of the resource.
224 * <p>
225 * Note: This class is exposed to the public, but intended to be used in the resource API
226 * implementation only. It is not for resource API user.
227 * </p>
228 */
Sho SHIMIZU6196cae2015-11-25 12:02:12 -0800229 @Beta
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800230 public static final class Discrete extends Resource {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800231 private Discrete() {
232 super();
233 }
234
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800235 private Discrete(ResourceId id) {
236 super(id);
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800237 }
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800238
239 /**
240 * The user of this methods must receive the return value as the correct type.
241 * Otherwise, this methods throws an exception.
242 *
243 * @param <T> type of the return value
244 * @return the volume of this resource
245 */
246 @SuppressWarnings("unchecked")
247 @Override
248 // TODO: consider receiving Class<T> as an argument. Which approach is convenient?
249 public <T> T volume() {
250 return (T) last();
251 }
252
253 @Override
254 public int hashCode() {
255 // the value returing from volume() is excluded due to optimization
256 return id().hashCode();
257 }
258
259 @Override
260 public boolean equals(Object obj) {
261 if (this == obj) {
262 return true;
263 }
264 if (obj == null || getClass() != obj.getClass()) {
265 return false;
266 }
267 final Discrete other = (Discrete) obj;
268 // the value returing from volume() is excluded due to optimization
269 return Objects.equals(this.id(), other.id());
270 }
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800271 }
272
273 /**
274 * Represents a resource path which specifies a resource which can be measured
275 * as continuous value. Bandwidth of a link is an example of the resource.
276 * <p>
277 * Note: This class is exposed to the public, but intended to be used in the resource API
278 * implementation only. It is not for resource API user.
279 */
Sho SHIMIZU6196cae2015-11-25 12:02:12 -0800280 @Beta
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800281 public static final class Continuous extends Resource {
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800282 private final double value;
283
Sho SHIMIZU5fb1ea32016-01-14 10:58:14 -0800284 private Continuous(ResourceId id, double value) {
285 super(id);
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800286 this.value = value;
287 }
288
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800289 /**
290 * The user of this methods must receive the return value as Double or double.
291 * Otherwise, this methods throws an exception.
292 *
293 * @param <T> type of the return value
294 * @return the volume of this resource
295 */
296 @SuppressWarnings("unchecked")
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800297 @Override
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800298 public <T> T volume() {
299 return (T) Double.valueOf(value);
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800300 }
301
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800302 @Override
303 public int hashCode() {
304 return Objects.hash(id(), value);
305 }
306
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800307 @Override
308 public boolean equals(Object obj) {
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800309 if (this == obj) {
310 return true;
311 }
312 if (obj == null || getClass() != obj.getClass()) {
313 return false;
314 }
315 final Continuous other = (Continuous) obj;
316 return Objects.equals(this.id(), other.id())
317 && Objects.equals(this.value, other.value);
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800318 }
319
320 /**
321 * Returns the value of the resource amount.
322 *
323 * @return the value of the resource amount
324 */
Sho SHIMIZU2d310222016-01-22 11:45:11 -0800325 // FIXME: overlapping a purpose with volume()
Sho SHIMIZU60ac58e2015-11-11 12:16:38 -0800326 public double value() {
327 return value;
328 }
329 }
Sho SHIMIZU7e6d18e2016-01-07 18:44:33 -0800330
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700331}