Sho SHIMIZU
Committed by Gerrit Code Review

Introduce ResourcePath.Key

Change-Id: I4efd5c13a12f2bad5482f5b432e2f1ef2c337805
1 /* 1 /*
2 - * Copyright 2015 Open Networking Laboratory 2 + * Copyright 2015-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableList; ...@@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableList;
21 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
22 import org.onosproject.net.PortNumber; 22 import org.onosproject.net.PortNumber;
23 23
24 -import java.util.LinkedList;
25 import java.util.List; 24 import java.util.List;
26 import java.util.Objects; 25 import java.util.Objects;
27 import java.util.Optional; 26 import java.util.Optional;
...@@ -50,12 +49,12 @@ import static com.google.common.base.Preconditions.checkState; ...@@ -50,12 +49,12 @@ import static com.google.common.base.Preconditions.checkState;
50 public abstract class ResourcePath { 49 public abstract class ResourcePath {
51 50
52 private final Discrete parent; 51 private final Discrete parent;
53 - private final Object last; 52 + private final Key key;
54 53
55 public static final Discrete ROOT = new Discrete(); 54 public static final Discrete ROOT = new Discrete();
56 55
57 public static ResourcePath discrete(DeviceId device) { 56 public static ResourcePath discrete(DeviceId device) {
58 - return new Discrete(ImmutableList.of(device)); 57 + return new Discrete(Key.of(device));
59 } 58 }
60 59
61 /** 60 /**
...@@ -66,10 +65,7 @@ public abstract class ResourcePath { ...@@ -66,10 +65,7 @@ public abstract class ResourcePath {
66 * @return resource path instance 65 * @return resource path instance
67 */ 66 */
68 public static ResourcePath discrete(DeviceId device, Object... components) { 67 public static ResourcePath discrete(DeviceId device, Object... components) {
69 - return new Discrete(ImmutableList.builder() 68 + return new Discrete(Key.of(device, components));
70 - .add(device)
71 - .add(components)
72 - .build());
73 } 69 }
74 70
75 /** 71 /**
...@@ -81,11 +77,7 @@ public abstract class ResourcePath { ...@@ -81,11 +77,7 @@ public abstract class ResourcePath {
81 * @return resource path instance 77 * @return resource path instance
82 */ 78 */
83 public static ResourcePath discrete(DeviceId device, PortNumber port, Object... components) { 79 public static ResourcePath discrete(DeviceId device, PortNumber port, Object... components) {
84 - return new Discrete(ImmutableList.builder() 80 + return new Discrete(Key.of(device, port, components));
85 - .add(device)
86 - .add(port)
87 - .add(components)
88 - .build());
89 } 81 }
90 82
91 /** 83 /**
...@@ -100,10 +92,7 @@ public abstract class ResourcePath { ...@@ -100,10 +92,7 @@ public abstract class ResourcePath {
100 checkArgument(components.length > 0, 92 checkArgument(components.length > 0,
101 "Length of components must be greater thant 0, but " + components.length); 93 "Length of components must be greater thant 0, but " + components.length);
102 94
103 - return new Continuous(ImmutableList.builder() 95 + return new Continuous(Key.of(device, components), value);
104 - .add(device)
105 - .add(components)
106 - .build(), value);
107 } 96 }
108 97
109 /** 98 /**
...@@ -116,49 +105,29 @@ public abstract class ResourcePath { ...@@ -116,49 +105,29 @@ public abstract class ResourcePath {
116 * @return resource path instance 105 * @return resource path instance
117 */ 106 */
118 public static ResourcePath continuous(double value, DeviceId device, PortNumber port, Object... components) { 107 public static ResourcePath continuous(double value, DeviceId device, PortNumber port, Object... components) {
119 - return new Continuous(ImmutableList.builder() 108 + return new Continuous(Key.of(device, port, components), value);
120 - .add(device)
121 - .add(port)
122 - .add(components)
123 - .build(), value);
124 } 109 }
125 110
126 /** 111 /**
127 - * Creates an resource path from the specified components. 112 + * Creates an resource path from the specified key.
128 * 113 *
129 - * @param components components of the path. The order represents hierarchical structure of the resource. 114 + * @param key key of the path
130 */ 115 */
131 - protected ResourcePath(List<Object> components) { 116 + protected ResourcePath(Key key) {
132 - checkNotNull(components); 117 + checkNotNull(key);
133 - checkArgument(!components.isEmpty());
134 118
135 - LinkedList<Object> children = new LinkedList<>(components); 119 + this.key = key;
136 - this.last = children.pollLast(); 120 + if (key.components.size() == 1) {
137 - if (children.isEmpty()) {
138 this.parent = ROOT; 121 this.parent = ROOT;
139 } else { 122 } else {
140 - this.parent = new Discrete(children); 123 + this.parent = new Discrete(key.parent());
141 } 124 }
142 } 125 }
143 126
144 - /**
145 - * Creates an resource path from the specified parent and child.
146 - *
147 - * @param parent the parent of this resource
148 - * @param last a child of the parent
149 - */
150 - protected ResourcePath(Discrete parent, Object last) {
151 - checkNotNull(parent);
152 - checkNotNull(last);
153 -
154 - this.parent = parent;
155 - this.last = last;
156 - }
157 -
158 // for serialization 127 // for serialization
159 private ResourcePath() { 128 private ResourcePath() {
160 this.parent = null; 129 this.parent = null;
161 - this.last = null; 130 + this.key = Key.ROOT;
162 } 131 }
163 132
164 /** 133 /**
...@@ -167,15 +136,7 @@ public abstract class ResourcePath { ...@@ -167,15 +136,7 @@ public abstract class ResourcePath {
167 * @return the components of this resource path 136 * @return the components of this resource path
168 */ 137 */
169 public List<Object> components() { 138 public List<Object> components() {
170 - LinkedList<Object> components = new LinkedList<>(); 139 + return key.components;
171 -
172 - ResourcePath current = this;
173 - while (current.parent().isPresent()) {
174 - components.addFirst(current.last);
175 - current = current.parent;
176 - }
177 -
178 - return components;
179 } 140 }
180 141
181 /** 142 /**
...@@ -199,7 +160,7 @@ public abstract class ResourcePath { ...@@ -199,7 +160,7 @@ public abstract class ResourcePath {
199 public ResourcePath child(Object child) { 160 public ResourcePath child(Object child) {
200 checkState(this instanceof Discrete); 161 checkState(this instanceof Discrete);
201 162
202 - return new Discrete((Discrete) this, child); 163 + return new Discrete(key().child(child));
203 } 164 }
204 165
205 /** 166 /**
...@@ -213,7 +174,7 @@ public abstract class ResourcePath { ...@@ -213,7 +174,7 @@ public abstract class ResourcePath {
213 public ResourcePath child(Object child, double value) { 174 public ResourcePath child(Object child, double value) {
214 checkState(this instanceof Discrete); 175 checkState(this instanceof Discrete);
215 176
216 - return new Continuous((Discrete) this, child, value); 177 + return new Continuous(key.child(child), value);
217 } 178 }
218 179
219 /** 180 /**
...@@ -223,12 +184,24 @@ public abstract class ResourcePath { ...@@ -223,12 +184,24 @@ public abstract class ResourcePath {
223 * The return value is equal to the last object of {@code components()}. 184 * The return value is equal to the last object of {@code components()}.
224 */ 185 */
225 public Object last() { 186 public Object last() {
226 - return last; 187 + 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;
227 } 200 }
228 201
229 @Override 202 @Override
230 public int hashCode() { 203 public int hashCode() {
231 - return Objects.hash(this.parent, this.last); 204 + return key.hashCode();
232 } 205 }
233 206
234 @Override 207 @Override
...@@ -240,15 +213,13 @@ public abstract class ResourcePath { ...@@ -240,15 +213,13 @@ public abstract class ResourcePath {
240 return false; 213 return false;
241 } 214 }
242 final ResourcePath that = (ResourcePath) obj; 215 final ResourcePath that = (ResourcePath) obj;
243 - return Objects.equals(this.parent, that.parent) 216 + return Objects.equals(this.key, that.key);
244 - && Objects.equals(this.last, that.last);
245 } 217 }
246 218
247 @Override 219 @Override
248 public String toString() { 220 public String toString() {
249 return MoreObjects.toStringHelper(this) 221 return MoreObjects.toStringHelper(this)
250 - .add("parent", parent) 222 + .add("key", key)
251 - .add("last", last)
252 .toString(); 223 .toString();
253 } 224 }
254 225
...@@ -266,12 +237,8 @@ public abstract class ResourcePath { ...@@ -266,12 +237,8 @@ public abstract class ResourcePath {
266 super(); 237 super();
267 } 238 }
268 239
269 - private Discrete(List<Object> components) { 240 + private Discrete(Key key) {
270 - super(components); 241 + super(key);
271 - }
272 -
273 - private Discrete(Discrete parent, Object last) {
274 - super(parent, last);
275 } 242 }
276 } 243 }
277 244
...@@ -284,17 +251,34 @@ public abstract class ResourcePath { ...@@ -284,17 +251,34 @@ public abstract class ResourcePath {
284 */ 251 */
285 @Beta 252 @Beta
286 public static final class Continuous extends ResourcePath { 253 public static final class Continuous extends ResourcePath {
287 - // Note: value is not taken into account for equality
288 private final double value; 254 private final double value;
289 255
290 - private Continuous(List<Object> components, double value) { 256 + private Continuous(Key key, double value) {
291 - super(components); 257 + super(key);
292 this.value = value; 258 this.value = value;
293 } 259 }
294 260
295 - public Continuous(Discrete parent, Object last, double value) { 261 + @Override
296 - super(parent, last); 262 + public int hashCode() {
297 - this.value = value; 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());
298 } 282 }
299 283
300 /** 284 /**
...@@ -306,4 +290,80 @@ public abstract class ResourcePath { ...@@ -306,4 +290,80 @@ public abstract class ResourcePath {
306 return value; 290 return value;
307 } 291 }
308 } 292 }
293 +
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 + }
309 } 369 }
......
...@@ -43,12 +43,12 @@ public class ResourcePathTest { ...@@ -43,12 +43,12 @@ public class ResourcePathTest {
43 ResourcePath sameAsResource1 = ResourcePath.discrete(D1, P1, VLAN1); 43 ResourcePath sameAsResource1 = ResourcePath.discrete(D1, P1, VLAN1);
44 ResourcePath resource2 = ResourcePath.discrete(D2, P1, VLAN1); 44 ResourcePath resource2 = ResourcePath.discrete(D2, P1, VLAN1);
45 ResourcePath resource3 = ResourcePath.continuous(BW1.bps(), D1, P1, BW1); 45 ResourcePath resource3 = ResourcePath.continuous(BW1.bps(), D1, P1, BW1);
46 - ResourcePath sameAsResource3 = ResourcePath.continuous(BW2.bps(), D1, P1, BW1); 46 + ResourcePath sameAsResource3 = ResourcePath.continuous(BW1.bps(), D1, P1, BW1);
47 47
48 new EqualsTester() 48 new EqualsTester()
49 .addEqualityGroup(resource1, sameAsResource1) 49 .addEqualityGroup(resource1, sameAsResource1)
50 .addEqualityGroup(resource2) 50 .addEqualityGroup(resource2)
51 - .addEqualityGroup(resource3, sameAsResource3) // this is intentional 51 + .addEqualityGroup(resource3, sameAsResource3)
52 .testEquals(); 52 .testEquals();
53 } 53 }
54 54
...@@ -60,6 +60,21 @@ public class ResourcePathTest { ...@@ -60,6 +60,21 @@ public class ResourcePathTest {
60 } 60 }
61 61
62 @Test 62 @Test
63 + public void testKeyEquality() {
64 + ResourcePath.Key key1 = ResourcePath.discrete(D1, P1, VLAN1).key();
65 + ResourcePath.Key sameAsKey1 = ResourcePath.discrete(D1, P1, VLAN1).key();
66 + ResourcePath.Key key2 = ResourcePath.discrete(D2, P1, VLAN1).key();
67 + ResourcePath.Key key3 = ResourcePath.continuous(BW1.bps(), D1, P1, BW1).key();
68 + // intentionally set a different value
69 + ResourcePath.Key sameAsKey3 = ResourcePath.continuous(BW2.bps(), D1, P1, BW1).key();
70 +
71 + new EqualsTester()
72 + .addEqualityGroup(key1, sameAsKey1)
73 + .addEqualityGroup(key2)
74 + .addEqualityGroup(key3, sameAsKey3);
75 + }
76 +
77 + @Test
63 public void testThereIsParent() { 78 public void testThereIsParent() {
64 ResourcePath path = ResourcePath.discrete(D1, P1, VLAN1); 79 ResourcePath path = ResourcePath.discrete(D1, P1, VLAN1);
65 ResourcePath parent = ResourcePath.discrete(D1, P1); 80 ResourcePath parent = ResourcePath.discrete(D1, P1);
......
1 /* 1 /*
2 - * Copyright 2014-2015 Open Networking Laboratory 2 + * Copyright 2014-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -430,6 +430,7 @@ public final class KryoNamespaces { ...@@ -430,6 +430,7 @@ public final class KryoNamespaces {
430 ResourcePath.class, 430 ResourcePath.class,
431 ResourcePath.Discrete.class, 431 ResourcePath.Discrete.class,
432 ResourcePath.Continuous.class, 432 ResourcePath.Continuous.class,
433 + ResourcePath.Key.class,
433 ResourceAllocation.class, 434 ResourceAllocation.class,
434 // Constraints 435 // Constraints
435 LambdaConstraint.class, 436 LambdaConstraint.class,
......
1 /* 1 /*
2 - * Copyright 2014-2015 Open Networking Laboratory 2 + * Copyright 2014-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -378,6 +378,11 @@ public class KryoSerializerTest { ...@@ -378,6 +378,11 @@ public class KryoSerializerTest {
378 } 378 }
379 379
380 @Test 380 @Test
381 + public void testResourceKey() {
382 + testSerializedEquals(ResourcePath.discrete(DID1, P1).key());
383 + }
384 +
385 + @Test
381 public void testResourceAllocation() { 386 public void testResourceAllocation() {
382 testSerializedEquals(new org.onosproject.net.newresource.ResourceAllocation( 387 testSerializedEquals(new org.onosproject.net.newresource.ResourceAllocation(
383 ResourcePath.discrete(DID1, P1, VLAN1), 388 ResourcePath.discrete(DID1, P1, VLAN1),
......