blob: 3bde82a6017f9c0a57b27fb22da093b8d95c6474 [file] [log] [blame]
Simon Huntc0f20c12016-05-09 09:30:20 -07001/*
2 * Copyright 2016-present 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
17package org.onosproject.ui.model.topo;
18
19import org.onosproject.net.ConnectPoint;
Simon Huntc13082f2016-08-03 21:20:23 -070020import org.onosproject.net.DeviceId;
Simon Huntc0f20c12016-05-09 09:30:20 -070021import org.onosproject.net.ElementId;
22import org.onosproject.net.Link;
Simon Hunt58a0dd02016-05-17 11:54:23 -070023import org.onosproject.net.PortNumber;
Simon Huntc13082f2016-08-03 21:20:23 -070024import org.onosproject.net.region.RegionId;
25
26import java.util.Comparator;
27
28import static com.google.common.base.Preconditions.checkArgument;
29import static com.google.common.base.Preconditions.checkNotNull;
Simon Huntc0f20c12016-05-09 09:30:20 -070030
31/**
32 * A canonical representation of an identifier for {@link UiLink}s.
33 */
34public final class UiLinkId {
35
Simon Huntc13082f2016-08-03 21:20:23 -070036 private static final String E_PORT_NULL = "Port number cannot be null";
37 private static final String E_DEVICE_ID_NULL = "Device ID cannot be null";
38 private static final String E_REGION_ID_NULL = "Region ID cannot be null";
39 private static final String E_IDENTICAL = "Region IDs cannot be same";
40
41 private static final Comparator<RegionId> REGION_ID_COMPARATOR =
42 (o1, o2) -> o1.toString().compareTo(o2.toString());
43
Simon Huntc0f20c12016-05-09 09:30:20 -070044 /**
45 * Designates the directionality of an underlying (uni-directional) link.
46 */
47 public enum Direction {
48 A_TO_B,
49 B_TO_A
50 }
51
Simon Huntc13082f2016-08-03 21:20:23 -070052 static final String CP_DELIMITER = "~";
53 static final String ID_PORT_DELIMITER = "/";
Simon Huntc0f20c12016-05-09 09:30:20 -070054
Simon Huntc13082f2016-08-03 21:20:23 -070055 private final RegionId regionA;
56 private final ElementId elementA;
Simon Hunt58a0dd02016-05-17 11:54:23 -070057 private final PortNumber portA;
Simon Huntc13082f2016-08-03 21:20:23 -070058
59 private final RegionId regionB;
60 private final ElementId elementB;
Simon Hunt58a0dd02016-05-17 11:54:23 -070061 private final PortNumber portB;
62
Simon Huntc0f20c12016-05-09 09:30:20 -070063 private final String idStr;
64
65 /**
66 * Creates a UI link identifier. It is expected that A comes before B when
67 * the two identifiers are naturally sorted, thus providing a representation
68 * which is invariant to whether A or B is source or destination of the
69 * underlying link.
70 *
Simon Huntc13082f2016-08-03 21:20:23 -070071 * @param a first element ID
Simon Hunt58a0dd02016-05-17 11:54:23 -070072 * @param pa first element port
Simon Huntc13082f2016-08-03 21:20:23 -070073 * @param b second element ID
Simon Hunt58a0dd02016-05-17 11:54:23 -070074 * @param pb second element port
Simon Huntc0f20c12016-05-09 09:30:20 -070075 */
Simon Hunt58a0dd02016-05-17 11:54:23 -070076 private UiLinkId(ElementId a, PortNumber pa, ElementId b, PortNumber pb) {
Simon Huntc13082f2016-08-03 21:20:23 -070077 elementA = a;
Simon Hunt58a0dd02016-05-17 11:54:23 -070078 portA = pa;
Simon Huntc13082f2016-08-03 21:20:23 -070079 elementB = b;
Simon Hunt58a0dd02016-05-17 11:54:23 -070080 portB = pb;
Simon Huntc0f20c12016-05-09 09:30:20 -070081
Simon Huntc13082f2016-08-03 21:20:23 -070082 regionA = null;
83 regionB = null;
84
Simon Hunt58a0dd02016-05-17 11:54:23 -070085 idStr = a + ID_PORT_DELIMITER + pa + CP_DELIMITER +
86 b + ID_PORT_DELIMITER + pb;
Simon Huntc0f20c12016-05-09 09:30:20 -070087 }
88
Simon Huntc13082f2016-08-03 21:20:23 -070089 /**
90 * Creates a UI link identifier. It is expected that A comes before B when
91 * the two identifiers are naturally sorted.
92 *
93 * @param a first region ID
94 * @param b second region ID
95 */
96 private UiLinkId(RegionId a, RegionId b) {
97 regionA = a;
98 regionB = b;
99
100 elementA = null;
101 elementB = null;
102 portA = null;
103 portB = null;
104
105 idStr = a + CP_DELIMITER + b;
106 }
107
108 /**
109 * Creates a UI link identifier, with region at one end and a device/port
110 * at the other.
111 *
112 * @param r region ID
113 * @param d device ID
114 * @param p port number
115 */
116 private UiLinkId(RegionId r, DeviceId d, PortNumber p) {
117 regionA = r;
118 elementB = d;
119 portB = p;
120
121 regionB = null;
122 elementA = null;
123 portA = null;
124
125 idStr = r + CP_DELIMITER + elementB + ID_PORT_DELIMITER + portB;
126 }
127
Simon Huntc0f20c12016-05-09 09:30:20 -0700128 @Override
129 public String toString() {
130 return idStr;
131 }
132
133 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700134 * Returns the identifier of the first element. Note that the returned
135 * value will be null if this identifier is for a region-region link.
Simon Huntc0f20c12016-05-09 09:30:20 -0700136 *
137 * @return first element identity
138 */
139 public ElementId elementA() {
Simon Huntc13082f2016-08-03 21:20:23 -0700140 return elementA;
Simon Huntc0f20c12016-05-09 09:30:20 -0700141 }
142
143 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700144 * Returns the port of the first element. Note that the returned
145 * value will be null if this identifier is for a region-region link.
Simon Hunt58a0dd02016-05-17 11:54:23 -0700146 *
147 * @return first element port
148 */
149 public PortNumber portA() {
150 return portA;
151 }
152
153 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700154 * Returns the identifier of the second element. Note that the returned
155 * value will be null if this identifier is for a region-region link.
Simon Huntc0f20c12016-05-09 09:30:20 -0700156 *
157 * @return second element identity
158 */
159 public ElementId elementB() {
Simon Huntc13082f2016-08-03 21:20:23 -0700160 return elementB;
Simon Huntc0f20c12016-05-09 09:30:20 -0700161 }
162
Simon Hunt58a0dd02016-05-17 11:54:23 -0700163 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700164 * Returns the port of the second element. Note that the returned
165 * value will be null if this identifier is for a region-region link.
Simon Hunt58a0dd02016-05-17 11:54:23 -0700166 *
167 * @return second element port
168 */
169 public PortNumber portB() {
170 return portB;
171 }
172
Simon Huntc13082f2016-08-03 21:20:23 -0700173 /**
174 * Returns the identity of the first region. Note that the returned value
175 * will be null if this identifier is for a device-device or device-host
176 * link.
177 *
178 * @return first region ID
179 */
180 public RegionId regionA() {
181 return regionA;
182 }
183
184 /**
185 * Returns the identity of the second region. Note that the returned value
186 * will be null if this identifier is for a device-device or device-host
187 * link.
188 *
189 * @return second region ID
190 */
191 public RegionId regionB() {
192 return regionB;
193 }
194
Simon Huntc0f20c12016-05-09 09:30:20 -0700195 @Override
196 public boolean equals(Object o) {
197 if (this == o) {
198 return true;
199 }
200 if (o == null || getClass() != o.getClass()) {
201 return false;
202 }
203
204 UiLinkId uiLinkId = (UiLinkId) o;
205 return idStr.equals(uiLinkId.idStr);
206 }
207
208 @Override
209 public int hashCode() {
210 return idStr.hashCode();
211 }
212
213 /**
214 * Returns the direction of the given link, or null if this link ID does
215 * not correspond to the given link.
216 *
217 * @param link the link to examine
218 * @return corresponding direction
219 */
220 Direction directionOf(Link link) {
221 ConnectPoint src = link.src();
222 ElementId srcId = src.elementId();
Simon Huntc13082f2016-08-03 21:20:23 -0700223 return elementA.equals(srcId) ? Direction.A_TO_B
224 : elementB.equals(srcId) ? Direction.B_TO_A
Simon Huntc0f20c12016-05-09 09:30:20 -0700225 : null;
226 }
227
228 /**
229 * Generates the canonical link identifier for the given link.
230 *
231 * @param link link for which the identifier is required
232 * @return link identifier
233 * @throws NullPointerException if any of the required fields are null
234 */
235 public static UiLinkId uiLinkId(Link link) {
236 ConnectPoint src = link.src();
237 ConnectPoint dst = link.dst();
238 if (src == null || dst == null) {
239 throw new NullPointerException("null src or dst connect point: " + link);
240 }
241
242 ElementId srcId = src.elementId();
243 ElementId dstId = dst.elementId();
Simon Huntc0f20c12016-05-09 09:30:20 -0700244
245 // canonicalize
246 int comp = srcId.toString().compareTo(dstId.toString());
Simon Hunt58a0dd02016-05-17 11:54:23 -0700247 return comp <= 0 ? new UiLinkId(srcId, src.port(), dstId, dst.port())
248 : new UiLinkId(dstId, dst.port(), srcId, src.port());
Simon Huntc0f20c12016-05-09 09:30:20 -0700249 }
Simon Huntc13082f2016-08-03 21:20:23 -0700250
251 /**
252 * Generates the canonical link identifier for a link between the
253 * specified region nodes.
254 *
255 * @param one the first region ID
256 * @param two the second region ID
257 * @return link identifier
258 * @throws NullPointerException if any of the required fields are null
259 * @throws IllegalArgumentException if the identifiers are identical
260 */
261 public static UiLinkId uiLinkId(RegionId one, RegionId two) {
262 checkNotNull(one, E_REGION_ID_NULL);
263 checkNotNull(two, E_REGION_ID_NULL);
264 checkArgument(!one.equals(two), E_IDENTICAL);
265
266 boolean flip = REGION_ID_COMPARATOR.compare(one, two) > 0;
267 return flip ? new UiLinkId(two, one) : new UiLinkId(one, two);
268 }
269
270 /**
271 * Generates the canonical link identifier for a link between the specified
272 * region and device/port.
273 *
274 * @param regionId region ID
275 * @param deviceId device ID
276 * @param portNumber port number
277 * @return link identifier
278 * @throws NullPointerException if any of the required fields are null
279 */
280 public static UiLinkId uiLinkId(RegionId regionId, DeviceId deviceId,
281 PortNumber portNumber) {
282 checkNotNull(regionId, E_REGION_ID_NULL);
283 checkNotNull(deviceId, E_DEVICE_ID_NULL);
284 checkNotNull(portNumber, E_PORT_NULL);
285
286 return new UiLinkId(regionId, deviceId, portNumber);
287 }
Simon Huntc0f20c12016-05-09 09:30:20 -0700288}