Simon Hunt

ONOS-4326: TopoRegions: Implement basic structure of response to 'topo2Start' event.

- this is WIP: still need to extract data from model cache.

Change-Id: I5ab843a1c352275a8da89964c886b660e3b8b616
...@@ -19,7 +19,7 @@ package org.onosproject.ui.model.topo; ...@@ -19,7 +19,7 @@ package org.onosproject.ui.model.topo;
19 /** 19 /**
20 * Represents a node drawn on the topology view (region, device, host). 20 * Represents a node drawn on the topology view (region, device, host).
21 */ 21 */
22 -abstract class UiNode extends UiElement { 22 +public abstract class UiNode extends UiElement {
23 23
24 /** 24 /**
25 * Default "layer" tag. 25 * Default "layer" tag.
......
...@@ -37,12 +37,19 @@ import org.onosproject.ui.model.topo.UiClusterMember; ...@@ -37,12 +37,19 @@ import org.onosproject.ui.model.topo.UiClusterMember;
37 import org.onosproject.ui.model.topo.UiDevice; 37 import org.onosproject.ui.model.topo.UiDevice;
38 import org.onosproject.ui.model.topo.UiHost; 38 import org.onosproject.ui.model.topo.UiHost;
39 import org.onosproject.ui.model.topo.UiLink; 39 import org.onosproject.ui.model.topo.UiLink;
40 +import org.onosproject.ui.model.topo.UiNode;
40 import org.onosproject.ui.model.topo.UiRegion; 41 import org.onosproject.ui.model.topo.UiRegion;
41 import org.onosproject.ui.model.topo.UiTopoLayout; 42 import org.onosproject.ui.model.topo.UiTopoLayout;
42 43
44 +import java.util.ArrayList;
45 +import java.util.HashMap;
46 +import java.util.HashSet;
43 import java.util.List; 47 import java.util.List;
48 +import java.util.Map;
49 +import java.util.Set;
44 50
45 import static com.google.common.base.Preconditions.checkNotNull; 51 import static com.google.common.base.Preconditions.checkNotNull;
52 +import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT;
46 53
47 /** 54 /**
48 * Facility for creating JSON messages to send to the topology view in the 55 * Facility for creating JSON messages to send to the topology view in the
...@@ -50,6 +57,11 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -50,6 +57,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
50 */ 57 */
51 class Topo2Jsonifier { 58 class Topo2Jsonifier {
52 59
60 + private static final String E_DEF_NOT_LAST =
61 + "UiNode.LAYER_DEFAULT not last in layer list";
62 + private static final String E_UNKNOWN_UI_NODE =
63 + "Unknown subclass of UiNode: ";
64 +
53 private final ObjectMapper mapper = new ObjectMapper(); 65 private final ObjectMapper mapper = new ObjectMapper();
54 66
55 private ServiceDirectory directory; 67 private ServiceDirectory directory;
...@@ -87,7 +99,10 @@ class Topo2Jsonifier { ...@@ -87,7 +99,10 @@ class Topo2Jsonifier {
87 portStatsService = directory.get(PortStatisticsService.class); 99 portStatsService = directory.get(PortStatisticsService.class);
88 topologyService = directory.get(TopologyService.class); 100 topologyService = directory.get(TopologyService.class);
89 tunnelService = directory.get(TunnelService.class); 101 tunnelService = directory.get(TunnelService.class);
102 + }
90 103
104 + // for unit testing
105 + Topo2Jsonifier() {
91 } 106 }
92 107
93 private ObjectNode objectNode() { 108 private ObjectNode objectNode() {
...@@ -156,46 +171,103 @@ class Topo2Jsonifier { ...@@ -156,46 +171,103 @@ class Topo2Jsonifier {
156 * view. 171 * view.
157 * 172 *
158 * @param region the region to transform to JSON 173 * @param region the region to transform to JSON
174 + * @param subRegions the subregions within this region
159 * @return a JSON representation of the data 175 * @return a JSON representation of the data
160 */ 176 */
161 - ObjectNode region(UiRegion region) { 177 + ObjectNode region(UiRegion region, Set<UiRegion> subRegions) {
162 ObjectNode payload = objectNode(); 178 ObjectNode payload = objectNode();
163 -
164 if (region == null) { 179 if (region == null) {
165 payload.put("note", "no-region"); 180 payload.put("note", "no-region");
166 return payload; 181 return payload;
167 } 182 }
183 + payload.put("id", region.idAsString());
184 + payload.set("subregions", jsonSubRegions(subRegions));
185 +
186 + List<String> layerTags = region.layerOrder();
187 + List<Set<UiNode>> splitDevices = splitByLayer(layerTags, region.devices());
188 + List<Set<UiNode>> splitHosts = splitByLayer(layerTags, region.hosts());
189 + Set<UiLink> links = region.links();
168 190
169 - payload.put("id", region.id().toString()); 191 + payload.set("devices", jsonGrouped(splitDevices));
192 + payload.set("hosts", jsonGrouped(splitHosts));
193 + payload.set("links", jsonLinks(links));
194 + payload.set("layerOrder", jsonStrings(layerTags));
170 195
171 - ArrayNode layerOrder = arrayNode(); 196 + return payload;
172 - payload.set("layerOrder", layerOrder); 197 + }
173 - region.layerOrder().forEach(layerOrder::add);
174 198
175 - ArrayNode devices = arrayNode(); 199 + private ArrayNode jsonSubRegions(Set<UiRegion> subregions) {
176 - payload.set("devices", devices); 200 + ArrayNode kids = arrayNode();
177 - for (UiDevice device : region.devices()) { 201 + if (subregions != null) {
178 - devices.add(json(device)); 202 + subregions.forEach(s -> kids.add(jsonClosedRegion(s)));
203 + }
204 + return kids;
179 } 205 }
180 206
181 - ArrayNode hosts = arrayNode(); 207 + private ArrayNode jsonStrings(List<String> strings) {
182 - payload.set("hosts", hosts); 208 + ArrayNode array = arrayNode();
183 - for (UiHost host : region.hosts()) { 209 + strings.forEach(array::add);
184 - hosts.add(json(host)); 210 + return array;
185 } 211 }
186 212
187 - ArrayNode links = arrayNode(); 213 + private ArrayNode jsonLinks(Set<UiLink> links) {
188 - payload.set("links", links); 214 + ArrayNode result = arrayNode();
189 - for (UiLink link : region.links()) { 215 + links.forEach(lnk -> result.add(json(lnk)));
190 - links.add(json(link)); 216 + return result;
191 } 217 }
192 218
219 + private ArrayNode jsonGrouped(List<Set<UiNode>> groupedNodes) {
220 + ArrayNode result = arrayNode();
221 + groupedNodes.forEach(g -> {
222 + ArrayNode subset = arrayNode();
223 + g.forEach(n -> subset.add(json(n)));
224 + result.add(subset);
225 + });
226 + return result;
227 + }
228 +
229 + /**
230 + * Returns a JSON payload that encapsulates the devices, hosts, links that
231 + * do not belong to any region.
232 + *
233 + * @param oDevices orphan devices
234 + * @param oHosts orphan hosts
235 + * @param oLinks orphan links
236 + * @param layerTags layer tags
237 + * @return a JSON representation of the data
238 + */
239 + ObjectNode orphans(Set<UiDevice> oDevices, Set<UiHost> oHosts,
240 + Set<UiLink> oLinks, List<String> layerTags) {
241 +
242 + ObjectNode payload = objectNode();
243 +
244 + List<Set<UiNode>> splitDevices = splitByLayer(layerTags, oDevices);
245 + List<Set<UiNode>> splitHosts = splitByLayer(layerTags, oHosts);
246 +
247 + payload.set("devices", jsonGrouped(splitDevices));
248 + payload.set("hosts", jsonGrouped(splitHosts));
249 + payload.set("links", jsonLinks(oLinks));
250 + payload.set("layerOrder", jsonStrings(layerTags));
251 +
193 return payload; 252 return payload;
194 } 253 }
195 254
255 + private ObjectNode json(UiNode node) {
256 + if (node instanceof UiRegion) {
257 + return jsonClosedRegion((UiRegion) node);
258 + }
259 + if (node instanceof UiDevice) {
260 + return json((UiDevice) node);
261 + }
262 + if (node instanceof UiHost) {
263 + return json((UiHost) node);
264 + }
265 + throw new IllegalStateException(E_UNKNOWN_UI_NODE + node.getClass());
266 + }
267 +
196 private ObjectNode json(UiDevice device) { 268 private ObjectNode json(UiDevice device) {
197 ObjectNode node = objectNode() 269 ObjectNode node = objectNode()
198 - .put("id", device.id().toString()) 270 + .put("id", device.idAsString())
199 .put("type", device.type()) 271 .put("type", device.type())
200 .put("online", device.isOnline()) 272 .put("online", device.isOnline())
201 .put("master", device.master().toString()) 273 .put("master", device.master().toString())
...@@ -216,7 +288,7 @@ class Topo2Jsonifier { ...@@ -216,7 +288,7 @@ class Topo2Jsonifier {
216 288
217 private ObjectNode json(UiHost host) { 289 private ObjectNode json(UiHost host) {
218 return objectNode() 290 return objectNode()
219 - .put("id", host.id().toString()) 291 + .put("id", host.idAsString())
220 .put("layer", host.layer()); 292 .put("layer", host.layer());
221 // TODO: complete host details 293 // TODO: complete host details
222 } 294 }
...@@ -224,9 +296,101 @@ class Topo2Jsonifier { ...@@ -224,9 +296,101 @@ class Topo2Jsonifier {
224 296
225 private ObjectNode json(UiLink link) { 297 private ObjectNode json(UiLink link) {
226 return objectNode() 298 return objectNode()
227 - .put("id", link.id().toString()); 299 + .put("id", link.idAsString());
228 // TODO: complete link details 300 // TODO: complete link details
229 } 301 }
230 302
231 303
304 + private ObjectNode jsonClosedRegion(UiRegion region) {
305 + return objectNode()
306 + .put("id", region.idAsString());
307 + // TODO: complete closed-region details
308 + }
309 +
310 +
311 + /**
312 + * Returns a JSON array representation of a list of regions. Note that the
313 + * information about each region is limited to what needs to be used to
314 + * show the regions as nodes on the view.
315 + *
316 + * @param regions the regions
317 + * @return a JSON representation of the minimal region information
318 + */
319 + public ArrayNode closedRegions(Set<UiRegion> regions) {
320 + ArrayNode array = arrayNode();
321 + for (UiRegion r : regions) {
322 + array.add(jsonClosedRegion(r));
323 + }
324 + return array;
325 + }
326 +
327 + /**
328 + * Returns a JSON array representation of a list of devices.
329 + *
330 + * @param devices the devices
331 + * @return a JSON representation of the devices
332 + */
333 + public ArrayNode devices(Set<UiDevice> devices) {
334 + ArrayNode array = arrayNode();
335 + for (UiDevice device : devices) {
336 + array.add(json(device));
337 + }
338 + return array;
339 + }
340 +
341 + /**
342 + * Returns a JSON array representation of a list of hosts.
343 + *
344 + * @param hosts the hosts
345 + * @return a JSON representation of the hosts
346 + */
347 + public ArrayNode hosts(Set<UiHost> hosts) {
348 + ArrayNode array = arrayNode();
349 + for (UiHost host : hosts) {
350 + array.add(json(host));
351 + }
352 + return array;
353 + }
354 +
355 + /**
356 + * Returns a JSON array representation of a list of links.
357 + *
358 + * @param links the links
359 + * @return a JSON representation of the links
360 + */
361 + public ArrayNode links(Set<UiLink> links) {
362 + ArrayNode array = arrayNode();
363 + for (UiLink link : links) {
364 + array.add(json(link));
365 + }
366 + return array;
367 + }
368 +
369 + // package-private for unit testing
370 + List<Set<UiNode>> splitByLayer(List<String> layerTags,
371 + Set<? extends UiNode> nodes) {
372 + final int nLayers = layerTags.size();
373 + if (!layerTags.get(nLayers - 1).equals(LAYER_DEFAULT)) {
374 + throw new IllegalArgumentException(E_DEF_NOT_LAST);
375 + }
376 +
377 + List<Set<UiNode>> splitList = new ArrayList<>(layerTags.size());
378 + Map<String, Set<UiNode>> byLayer = new HashMap<>(layerTags.size());
379 +
380 + for (String tag : layerTags) {
381 + Set<UiNode> set = new HashSet<>();
382 + byLayer.put(tag, set);
383 + splitList.add(set);
384 + }
385 +
386 + for (UiNode n : nodes) {
387 + String which = n.layer();
388 + if (!layerTags.contains(which)) {
389 + which = LAYER_DEFAULT;
390 + }
391 + byLayer.get(which).add(n);
392 + }
393 +
394 + return splitList;
395 + }
232 } 396 }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
17 package org.onosproject.ui.impl.topo; 17 package org.onosproject.ui.impl.topo;
18 18
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import com.google.common.collect.ImmutableList;
20 import com.google.common.collect.ImmutableSet; 21 import com.google.common.collect.ImmutableSet;
21 import org.onlab.osgi.ServiceDirectory; 22 import org.onlab.osgi.ServiceDirectory;
22 import org.onosproject.ui.RequestHandler; 23 import org.onosproject.ui.RequestHandler;
...@@ -24,6 +25,9 @@ import org.onosproject.ui.UiConnection; ...@@ -24,6 +25,9 @@ import org.onosproject.ui.UiConnection;
24 import org.onosproject.ui.UiMessageHandler; 25 import org.onosproject.ui.UiMessageHandler;
25 import org.onosproject.ui.impl.UiWebSocket; 26 import org.onosproject.ui.impl.UiWebSocket;
26 import org.onosproject.ui.model.topo.UiClusterMember; 27 import org.onosproject.ui.model.topo.UiClusterMember;
28 +import org.onosproject.ui.model.topo.UiDevice;
29 +import org.onosproject.ui.model.topo.UiHost;
30 +import org.onosproject.ui.model.topo.UiLink;
27 import org.onosproject.ui.model.topo.UiRegion; 31 import org.onosproject.ui.model.topo.UiRegion;
28 import org.onosproject.ui.model.topo.UiTopoLayout; 32 import org.onosproject.ui.model.topo.UiTopoLayout;
29 import org.slf4j.Logger; 33 import org.slf4j.Logger;
...@@ -31,6 +35,9 @@ import org.slf4j.LoggerFactory; ...@@ -31,6 +35,9 @@ import org.slf4j.LoggerFactory;
31 35
32 import java.util.Collection; 36 import java.util.Collection;
33 import java.util.List; 37 import java.util.List;
38 +import java.util.Set;
39 +
40 +import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT;
34 41
35 /* 42 /*
36 NOTES: 43 NOTES:
...@@ -58,11 +65,14 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { ...@@ -58,11 +65,14 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
58 private static final String TOPO2_STOP = "topo2Stop"; 65 private static final String TOPO2_STOP = "topo2Stop";
59 66
60 // === Outbound event identifiers 67 // === Outbound event identifiers
68 + private static final String ALL_INSTANCES = "topo2AllInstances";
61 private static final String CURRENT_LAYOUT = "topo2CurrentLayout"; 69 private static final String CURRENT_LAYOUT = "topo2CurrentLayout";
62 private static final String CURRENT_REGION = "topo2CurrentRegion"; 70 private static final String CURRENT_REGION = "topo2CurrentRegion";
63 - private static final String ALL_INSTANCES = "topo2AllInstances"; 71 + private static final String PEER_REGIONS = "topo2PeerRegions";
72 + private static final String ORPHANS = "topo2Orphans";
64 private static final String TOPO_START_DONE = "topo2StartDone"; 73 private static final String TOPO_START_DONE = "topo2StartDone";
65 74
75 +
66 private UiTopoSession topoSession; 76 private UiTopoSession topoSession;
67 private Topo2Jsonifier t2json; 77 private Topo2Jsonifier t2json;
68 78
...@@ -99,18 +109,36 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { ...@@ -99,18 +109,36 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
99 109
100 log.debug("topo2Start: {}", payload); 110 log.debug("topo2Start: {}", payload);
101 111
112 + // this is the list of ONOS cluster members
102 List<UiClusterMember> instances = topoSession.getAllInstances(); 113 List<UiClusterMember> instances = topoSession.getAllInstances();
103 sendMessage(ALL_INSTANCES, t2json.instances(instances)); 114 sendMessage(ALL_INSTANCES, t2json.instances(instances));
104 115
116 + // this is the layout that the user has chosen to display
105 UiTopoLayout currentLayout = topoSession.currentLayout(); 117 UiTopoLayout currentLayout = topoSession.currentLayout();
106 sendMessage(CURRENT_LAYOUT, t2json.layout(currentLayout)); 118 sendMessage(CURRENT_LAYOUT, t2json.layout(currentLayout));
107 119
120 + // this is the region that is associated with the current layout
121 + // this message includes details of the sub-regions, devices,
122 + // hosts, and links within the region
123 + // (as well as layer-order hints)
108 UiRegion region = topoSession.getRegion(currentLayout); 124 UiRegion region = topoSession.getRegion(currentLayout);
109 - sendMessage(CURRENT_REGION, t2json.region(region)); 125 + Set<UiRegion> kids = topoSession.getSubRegions(currentLayout);
110 - 126 + sendMessage(CURRENT_REGION, t2json.region(region, kids));
111 - // TODO: send information about devices/hosts/links in non-region 127 +
112 - // TODO: send information about "linked, peer" regions 128 + // these are the regions that are siblings to this one
113 - 129 + Set<UiRegion> peers = topoSession.getPeerRegions(currentLayout);
130 + ObjectNode peersPayload = objectNode();
131 + peersPayload.set("peers", t2json.closedRegions(peers));
132 + sendMessage(PEER_REGIONS, peersPayload);
133 +
134 + // return devices, hosts, links belonging to no region
135 + Set<UiDevice> oDevices = topoSession.getOrphanDevices();
136 + Set<UiHost> oHosts = topoSession.getOrphanHosts();
137 + Set<UiLink> oLinks = topoSession.getOrphanLinks();
138 + List<String> oLayers = getOrphanLayerOrder();
139 + sendMessage(ORPHANS, t2json.orphans(oDevices, oHosts, oLinks, oLayers));
140 +
141 + // finally, tell the UI that we are done
114 sendMessage(TOPO_START_DONE, null); 142 sendMessage(TOPO_START_DONE, null);
115 143
116 144
...@@ -122,6 +150,16 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { ...@@ -122,6 +150,16 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
122 // sendAllHosts(); 150 // sendAllHosts();
123 // sendTopoStartDone(); 151 // sendTopoStartDone();
124 } 152 }
153 +
154 +
155 + }
156 +
157 + // TODO: we need to decide on how this should really get populated.
158 + // For example, to be "backward compatible", this should really be
159 + // [ LAYER_OPTICAL, LAYER_PACKET, LAYER_DEFAULT ]
160 + private List<String> getOrphanLayerOrder() {
161 + // NOTE that LAYER_DEFAULT must always be last in the array
162 + return ImmutableList.of(LAYER_DEFAULT);
125 } 163 }
126 164
127 private final class Topo2Stop extends RequestHandler { 165 private final class Topo2Stop extends RequestHandler {
......
...@@ -22,12 +22,17 @@ import org.onosproject.ui.impl.topo.model.UiModelEvent; ...@@ -22,12 +22,17 @@ import org.onosproject.ui.impl.topo.model.UiModelEvent;
22 import org.onosproject.ui.impl.topo.model.UiModelListener; 22 import org.onosproject.ui.impl.topo.model.UiModelListener;
23 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; 23 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
24 import org.onosproject.ui.model.topo.UiClusterMember; 24 import org.onosproject.ui.model.topo.UiClusterMember;
25 +import org.onosproject.ui.model.topo.UiDevice;
26 +import org.onosproject.ui.model.topo.UiHost;
27 +import org.onosproject.ui.model.topo.UiLink;
25 import org.onosproject.ui.model.topo.UiRegion; 28 import org.onosproject.ui.model.topo.UiRegion;
26 import org.onosproject.ui.model.topo.UiTopoLayout; 29 import org.onosproject.ui.model.topo.UiTopoLayout;
27 import org.slf4j.Logger; 30 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 31 import org.slf4j.LoggerFactory;
29 32
33 +import java.util.Collections;
30 import java.util.List; 34 import java.util.List;
35 +import java.util.Set;
31 36
32 /** 37 /**
33 * Coordinates with the {@link UiTopoLayoutService} to access 38 * Coordinates with the {@link UiTopoLayoutService} to access
...@@ -44,6 +49,7 @@ import java.util.List; ...@@ -44,6 +49,7 @@ import java.util.List;
44 * interact with it when topo-related events come in from the client. 49 * interact with it when topo-related events come in from the client.
45 */ 50 */
46 public class UiTopoSession implements UiModelListener { 51 public class UiTopoSession implements UiModelListener {
52 +
47 private final Logger log = LoggerFactory.getLogger(getClass()); 53 private final Logger log = LoggerFactory.getLogger(getClass());
48 54
49 private final UiWebSocket webSocket; 55 private final UiWebSocket webSocket;
...@@ -73,6 +79,13 @@ public class UiTopoSession implements UiModelListener { ...@@ -73,6 +79,13 @@ public class UiTopoSession implements UiModelListener {
73 this.layoutService = layoutService; 79 this.layoutService = layoutService;
74 } 80 }
75 81
82 + // constructs a neutered instance, for unit testing
83 + UiTopoSession() {
84 + webSocket = null;
85 + username = null;
86 + sharedModel = null;
87 + }
88 +
76 /** 89 /**
77 * Initializes the session; registering with the shared model. 90 * Initializes the session; registering with the shared model.
78 */ 91 */
...@@ -154,6 +167,68 @@ public class UiTopoSession implements UiModelListener { ...@@ -154,6 +167,68 @@ public class UiTopoSession implements UiModelListener {
154 * @return region that the layout is based upon 167 * @return region that the layout is based upon
155 */ 168 */
156 public UiRegion getRegion(UiTopoLayout layout) { 169 public UiRegion getRegion(UiTopoLayout layout) {
157 - return sharedModel.getRegion(layout); 170 + return sharedModel.getRegion(layout.regionId());
171 + }
172 +
173 + /**
174 + * Returns the regions that are "peers" to this region. That is, based on
175 + * the layout the user is viewing, all the regions that are associated with
176 + * layouts that are children of the parent layout to this layout.
177 + *
178 + * @param layout the layout being viewed
179 + * @return all regions that are "siblings" to this layout's region
180 + */
181 + public Set<UiRegion> getPeerRegions(UiTopoLayout layout) {
182 + UiRegion currentRegion = getRegion(layout);
183 +
184 + // TODO: consult topo layout service to get hierarchy info...
185 + // TODO: then consult shared model to get regions
186 + return Collections.emptySet();
187 + }
188 +
189 + /**
190 + * Returns the subregions of the region in the specified layout.
191 + *
192 + * @param layout the layout being viewed
193 + * @return all regions that are "contained within" this layout's region
194 + */
195 + public Set<UiRegion> getSubRegions(UiTopoLayout layout) {
196 + UiRegion currentRegion = getRegion(layout);
197 +
198 + // TODO: consult topo layout service to get child layouts...
199 + // TODO: then consult shared model to get regions
200 + return Collections.emptySet();
201 + }
202 +
203 +
204 + /**
205 + * Returns all devices that are not in a region.
206 + *
207 + * @return all devices not in a region
208 + */
209 + public Set<UiDevice> getOrphanDevices() {
210 + // TODO: get devices with no region
211 + return Collections.emptySet();
212 + }
213 +
214 + /**
215 + * Returns all hosts that are not in a region.
216 + *
217 + * @return all hosts not in a region
218 + */
219 + public Set<UiHost> getOrphanHosts() {
220 + // TODO: get hosts with no region
221 + return Collections.emptySet();
222 + }
223 +
224 + /**
225 + * Returns all links that are not in a region.
226 + *
227 + * @return all links not in a region
228 + */
229 + public Set<UiLink> getOrphanLinks() {
230 + // TODO: get links with no region
231 + return Collections.emptySet();
158 } 232 }
233 +
159 } 234 }
......
...@@ -55,6 +55,7 @@ import org.onosproject.net.link.LinkListener; ...@@ -55,6 +55,7 @@ import org.onosproject.net.link.LinkListener;
55 import org.onosproject.net.link.LinkService; 55 import org.onosproject.net.link.LinkService;
56 import org.onosproject.net.region.Region; 56 import org.onosproject.net.region.Region;
57 import org.onosproject.net.region.RegionEvent; 57 import org.onosproject.net.region.RegionEvent;
58 +import org.onosproject.net.region.RegionId;
58 import org.onosproject.net.region.RegionListener; 59 import org.onosproject.net.region.RegionListener;
59 import org.onosproject.net.region.RegionService; 60 import org.onosproject.net.region.RegionService;
60 import org.onosproject.net.statistic.StatisticService; 61 import org.onosproject.net.statistic.StatisticService;
...@@ -62,15 +63,11 @@ import org.onosproject.net.topology.TopologyService; ...@@ -62,15 +63,11 @@ import org.onosproject.net.topology.TopologyService;
62 import org.onosproject.ui.impl.topo.UiTopoSession; 63 import org.onosproject.ui.impl.topo.UiTopoSession;
63 import org.onosproject.ui.model.ServiceBundle; 64 import org.onosproject.ui.model.ServiceBundle;
64 import org.onosproject.ui.model.topo.UiClusterMember; 65 import org.onosproject.ui.model.topo.UiClusterMember;
65 -import org.onosproject.ui.model.topo.UiElement;
66 import org.onosproject.ui.model.topo.UiRegion; 66 import org.onosproject.ui.model.topo.UiRegion;
67 -import org.onosproject.ui.model.topo.UiTopoLayout;
68 import org.slf4j.Logger; 67 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory; 68 import org.slf4j.LoggerFactory;
70 69
71 -import java.util.HashSet;
72 import java.util.List; 70 import java.util.List;
73 -import java.util.Set;
74 import java.util.concurrent.ExecutorService; 71 import java.util.concurrent.ExecutorService;
75 import java.util.concurrent.Executors; 72 import java.util.concurrent.Executors;
76 73
...@@ -210,23 +207,14 @@ public final class UiSharedTopologyModel ...@@ -210,23 +207,14 @@ public final class UiSharedTopologyModel
210 return cache.getAllClusterMembers(); 207 return cache.getAllClusterMembers();
211 } 208 }
212 209
213 - public Set<UiElement> getElements(UiTopoLayout layout) {
214 - Set<UiElement> results = new HashSet<>();
215 -
216 - // TODO: figure out how to extract the appropriate nodes
217 - // from the cache, for the given layout.
218 -
219 - return results;
220 - }
221 -
222 /** 210 /**
223 - * Returns the region for the given layout. 211 + * Returns the region for the given identifier.
224 * 212 *
225 - * @param layout layout filter 213 + * @param id region identifier
226 - * @return the region the layout is based upon 214 + * @return the region
227 */ 215 */
228 - public UiRegion getRegion(UiTopoLayout layout) { 216 + public UiRegion getRegion(RegionId id) {
229 - return cache.accessRegion(layout.regionId()); 217 + return cache.accessRegion(id);
230 } 218 }
231 219
232 // ===================================================================== 220 // =====================================================================
......
1 +/*
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 +
17 +package org.onosproject.ui.impl.topo;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import org.junit.Test;
22 +import org.onosproject.ui.impl.AbstractUiImplTest;
23 +import org.onosproject.ui.model.topo.UiNode;
24 +
25 +import java.util.List;
26 +import java.util.Set;
27 +
28 +import static org.junit.Assert.assertEquals;
29 +import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT;
30 +import static org.onosproject.ui.model.topo.UiNode.LAYER_OPTICAL;
31 +import static org.onosproject.ui.model.topo.UiNode.LAYER_PACKET;
32 +
33 +/**
34 + * Unit tests for {@link Topo2ViewMessageHandler}.
35 + */
36 +public class Topo2JsonifierTest extends AbstractUiImplTest {
37 +
38 + // mock node class for testing
39 + private static class MockNode extends UiNode {
40 + private final String id;
41 +
42 + MockNode(String id, String layer) {
43 + this.id = id;
44 + setLayer(layer);
45 + }
46 +
47 + @Override
48 + public String idAsString() {
49 + return id;
50 + }
51 +
52 + @Override
53 + public String toString() {
54 + return id;
55 + }
56 + }
57 +
58 + private static final List<String> ALL_TAGS = ImmutableList.of(
59 + LAYER_OPTICAL, LAYER_PACKET, LAYER_DEFAULT
60 + );
61 +
62 + private static final List<String> PKT_DEF_TAGS = ImmutableList.of(
63 + LAYER_PACKET, LAYER_DEFAULT
64 + );
65 +
66 + private static final List<String> DEF_TAG_ONLY = ImmutableList.of(
67 + LAYER_DEFAULT
68 + );
69 +
70 + private static final MockNode NODE_A = new MockNode("A-O", LAYER_OPTICAL);
71 + private static final MockNode NODE_B = new MockNode("B-P", LAYER_PACKET);
72 + private static final MockNode NODE_C = new MockNode("C-O", LAYER_OPTICAL);
73 + private static final MockNode NODE_D = new MockNode("D-D", LAYER_DEFAULT);
74 + private static final MockNode NODE_E = new MockNode("E-P", LAYER_PACKET);
75 + private static final MockNode NODE_F = new MockNode("F-r", "random");
76 +
77 + private static final Set<MockNode> NODES = ImmutableSet.of(
78 + NODE_A, NODE_B, NODE_C, NODE_D, NODE_E, NODE_F
79 + );
80 +
81 + private Topo2Jsonifier t2 = new Topo2Jsonifier();
82 +
83 + @Test
84 + public void threeLayers() {
85 + print("threeLayers()");
86 +
87 + List<Set<UiNode>> result = t2.splitByLayer(ALL_TAGS, NODES);
88 + print(result);
89 +
90 + assertEquals("wrong split size", 3, result.size());
91 + Set<UiNode> opt = result.get(0);
92 + Set<UiNode> pkt = result.get(1);
93 + Set<UiNode> def = result.get(2);
94 +
95 + assertEquals("opt bad size", 2, opt.size());
96 + assertEquals("missing node A", true, opt.contains(NODE_A));
97 + assertEquals("missing node C", true, opt.contains(NODE_C));
98 +
99 + assertEquals("pkt bad size", 2, pkt.size());
100 + assertEquals("missing node B", true, pkt.contains(NODE_B));
101 + assertEquals("missing node E", true, pkt.contains(NODE_E));
102 +
103 + assertEquals("def bad size", 2, def.size());
104 + assertEquals("missing node D", true, def.contains(NODE_D));
105 + assertEquals("missing node F", true, def.contains(NODE_F));
106 + }
107 +
108 + @Test
109 + public void twoLayers() {
110 + print("twoLayers()");
111 +
112 + List<Set<UiNode>> result = t2.splitByLayer(PKT_DEF_TAGS, NODES);
113 + print(result);
114 +
115 + assertEquals("wrong split size", 2, result.size());
116 + Set<UiNode> pkt = result.get(0);
117 + Set<UiNode> def = result.get(1);
118 +
119 + assertEquals("pkt bad size", 2, pkt.size());
120 + assertEquals("missing node B", true, pkt.contains(NODE_B));
121 + assertEquals("missing node E", true, pkt.contains(NODE_E));
122 +
123 + assertEquals("def bad size", 4, def.size());
124 + assertEquals("missing node D", true, def.contains(NODE_D));
125 + assertEquals("missing node F", true, def.contains(NODE_F));
126 + assertEquals("missing node A", true, def.contains(NODE_A));
127 + assertEquals("missing node C", true, def.contains(NODE_C));
128 + }
129 +
130 + @Test
131 + public void oneLayer() {
132 + print("oneLayer()");
133 +
134 + List<Set<UiNode>> result = t2.splitByLayer(DEF_TAG_ONLY, NODES);
135 + print(result);
136 +
137 + assertEquals("wrong split size", 1, result.size());
138 + Set<UiNode> def = result.get(0);
139 +
140 + assertEquals("def bad size", 6, def.size());
141 + assertEquals("missing node D", true, def.contains(NODE_D));
142 + assertEquals("missing node F", true, def.contains(NODE_F));
143 + assertEquals("missing node A", true, def.contains(NODE_A));
144 + assertEquals("missing node C", true, def.contains(NODE_C));
145 + assertEquals("missing node B", true, def.contains(NODE_B));
146 + assertEquals("missing node E", true, def.contains(NODE_E));
147 + }
148 +}