Simon Hunt
Committed by Gerrit Code Review

ONOS-1479 -- GUI - augmenting topology view for extensibility:

- Added id field to property panel, as well as overloaded constructors.
- Added modify*Details() methods to UiTopoOverlay.
- Cleaned up use of string constants.
- Reworked RequestDetails in Topo view msg handler (and base).
- Fixed bug in topo UI where selected host title click caused exception on server.

Change-Id: Ib2a3cf60fae8ad8cda77a3b6933ee758262e6f3c
...@@ -38,9 +38,7 @@ public final class JsonUtils { ...@@ -38,9 +38,7 @@ public final class JsonUtils {
38 * @param sid sequence ID 38 * @param sid sequence ID
39 * @param payload event payload 39 * @param payload event payload
40 * @return the object node representation 40 * @return the object node representation
41 - * @deprecated in Cardinal Release
42 */ 41 */
43 - @Deprecated
44 public static ObjectNode envelope(String type, long sid, ObjectNode payload) { 42 public static ObjectNode envelope(String type, long sid, ObjectNode payload) {
45 ObjectNode event = MAPPER.createObjectNode(); 43 ObjectNode event = MAPPER.createObjectNode();
46 event.put("event", type); 44 event.put("event", type);
......
...@@ -26,7 +26,10 @@ import org.slf4j.LoggerFactory; ...@@ -26,7 +26,10 @@ import org.slf4j.LoggerFactory;
26 */ 26 */
27 public class UiTopoOverlay { 27 public class UiTopoOverlay {
28 28
29 - private final Logger log = LoggerFactory.getLogger(getClass()); 29 + /**
30 + * Logger for this overlay.
31 + */
32 + protected final Logger log = LoggerFactory.getLogger(getClass());
30 33
31 private final String id; 34 private final String id;
32 35
...@@ -72,7 +75,7 @@ public class UiTopoOverlay { ...@@ -72,7 +75,7 @@ public class UiTopoOverlay {
72 /** 75 /**
73 * Callback invoked to destroy this instance by cleaning up any 76 * Callback invoked to destroy this instance by cleaning up any
74 * internal state ready for garbage collection. 77 * internal state ready for garbage collection.
75 - * This default implementation does nothing. 78 + * This default implementation holds no state and does nothing.
76 */ 79 */
77 public void destroy() { 80 public void destroy() {
78 } 81 }
...@@ -85,4 +88,24 @@ public class UiTopoOverlay { ...@@ -85,4 +88,24 @@ public class UiTopoOverlay {
85 */ 88 */
86 public void modifySummary(PropertyPanel pp) { 89 public void modifySummary(PropertyPanel pp) {
87 } 90 }
91 +
92 + /**
93 + * Callback to modify the contents of the details panel for
94 + * a selected device.
95 + * This default implementation does nothing.
96 + *
97 + * @param pp property panel model of summary data
98 + */
99 + public void modifyDeviceDetails(PropertyPanel pp) {
100 + }
101 +
102 + /**
103 + * Callback to modify the contents of the details panel for
104 + * a selected host.
105 + * This default implementation does nothing.
106 + *
107 + * @param pp property panel model of summary data
108 + */
109 + public void modifyHostDetails(PropertyPanel pp) {
110 + }
88 } 111 }
......
...@@ -19,6 +19,7 @@ package org.onosproject.ui.topo; ...@@ -19,6 +19,7 @@ package org.onosproject.ui.topo;
19 19
20 import com.google.common.collect.Sets; 20 import com.google.common.collect.Sets;
21 21
22 +import java.text.DecimalFormat;
22 import java.util.ArrayList; 23 import java.util.ArrayList;
23 import java.util.List; 24 import java.util.List;
24 import java.util.Set; 25 import java.util.Set;
...@@ -30,6 +31,7 @@ public class PropertyPanel { ...@@ -30,6 +31,7 @@ public class PropertyPanel {
30 31
31 private String title; 32 private String title;
32 private String typeId; 33 private String typeId;
34 + private String id;
33 private List<Prop> properties = new ArrayList<>(); 35 private List<Prop> properties = new ArrayList<>();
34 36
35 /** 37 /**
...@@ -56,6 +58,19 @@ public class PropertyPanel { ...@@ -56,6 +58,19 @@ public class PropertyPanel {
56 } 58 }
57 59
58 /** 60 /**
61 + * Adds an ID field to the panel data, to be included in
62 + * the returned JSON data to the client.
63 + *
64 + * @param id the identifier
65 + * @return self, for chaining
66 + */
67 + public PropertyPanel id(String id) {
68 + this.id = id;
69 + return this;
70 + }
71 +
72 +
73 + /**
59 * Returns the title text. 74 * Returns the title text.
60 * 75 *
61 * @return title text 76 * @return title text
...@@ -74,6 +89,15 @@ public class PropertyPanel { ...@@ -74,6 +89,15 @@ public class PropertyPanel {
74 } 89 }
75 90
76 /** 91 /**
92 + * Returns the internal ID.
93 + *
94 + * @return the ID
95 + */
96 + public String id() {
97 + return id;
98 + }
99 +
100 + /**
77 * Returns the list of properties to be displayed. 101 * Returns the list of properties to be displayed.
78 * 102 *
79 * @return the property list 103 * @return the property list
...@@ -137,6 +161,8 @@ public class PropertyPanel { ...@@ -137,6 +161,8 @@ public class PropertyPanel {
137 161
138 // ==================== 162 // ====================
139 163
164 + private static final DecimalFormat DF0 = new DecimalFormat("#,###");
165 +
140 /** 166 /**
141 * Simple data carrier for a property, composed of a key/value pair. 167 * Simple data carrier for a property, composed of a key/value pair.
142 */ 168 */
...@@ -156,6 +182,26 @@ public class PropertyPanel { ...@@ -156,6 +182,26 @@ public class PropertyPanel {
156 } 182 }
157 183
158 /** 184 /**
185 + * Constructs a property data value.
186 + * @param key property key
187 + * @param value property value
188 + */
189 + public Prop(String key, int value) {
190 + this.key = key;
191 + this.value = DF0.format(value);
192 + }
193 +
194 + /**
195 + * Constructs a property data value.
196 + * @param key property key
197 + * @param value property value
198 + */
199 + public Prop(String key, long value) {
200 + this.key = key;
201 + this.value = DF0.format(value);
202 + }
203 +
204 + /**
159 * Returns the property's key. 205 * Returns the property's key.
160 * 206 *
161 * @return the key 207 * @return the key
......
...@@ -74,12 +74,20 @@ public class TopoOverlayCache { ...@@ -74,12 +74,20 @@ public class TopoOverlayCache {
74 return isNullOrEmpty(id) ? NONE : overlays.get(id); 74 return isNullOrEmpty(id) ? NONE : overlays.get(id);
75 } 75 }
76 76
77 + /**
78 + * Returns the current overlay instance.
79 + * Note that this method always returns a reference; when there is no
80 + * overlay selected the "NULL" overlay instance is returned.
81 + *
82 + * @return the current overlay
83 + */
77 public UiTopoOverlay currentOverlay() { 84 public UiTopoOverlay currentOverlay() {
78 return current; 85 return current;
79 } 86 }
80 87
81 /** 88 /**
82 - * Returns the number of overlays in the cache. 89 + * Returns the number of overlays in the cache. Remember that this
90 + * includes the "NULL" overlay, representing "no overlay selected".
83 * 91 *
84 * @return number of overlays 92 * @return number of overlays
85 */ 93 */
...@@ -88,16 +96,13 @@ public class TopoOverlayCache { ...@@ -88,16 +96,13 @@ public class TopoOverlayCache {
88 } 96 }
89 97
90 98
91 - 99 + // overlay instance representing "no overlay selected"
92 private static class NullOverlay extends UiTopoOverlay { 100 private static class NullOverlay extends UiTopoOverlay {
93 public NullOverlay() { 101 public NullOverlay() {
94 super(null); 102 super(null);
95 } 103 }
96 104
97 - @Override 105 + // override activate and deactivate, so no log messages are written
98 - public void init() {
99 - }
100 -
101 @Override 106 @Override
102 public void activate() { 107 public void activate() {
103 } 108 }
...@@ -105,9 +110,5 @@ public class TopoOverlayCache { ...@@ -105,9 +110,5 @@ public class TopoOverlayCache {
105 @Override 110 @Override
106 public void deactivate() { 111 public void deactivate() {
107 } 112 }
108 -
109 - @Override
110 - public void destroy() {
111 - }
112 } 113 }
113 } 114 }
......
...@@ -85,6 +85,7 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; ...@@ -85,6 +85,7 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
85 */ 85 */
86 public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { 86 public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
87 87
88 + // incoming event types
88 private static final String REQ_DETAILS = "requestDetails"; 89 private static final String REQ_DETAILS = "requestDetails";
89 private static final String UPDATE_META = "updateMeta"; 90 private static final String UPDATE_META = "updateMeta";
90 private static final String ADD_HOST_INTENT = "addHostIntent"; 91 private static final String ADD_HOST_INTENT = "addHostIntent";
...@@ -107,6 +108,33 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -107,6 +108,33 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
107 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay"; 108 private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
108 private static final String TOPO_STOP = "topoStop"; 109 private static final String TOPO_STOP = "topoStop";
109 110
111 + // outgoing event types
112 + private static final String SHOW_SUMMARY = "showSummary";
113 + private static final String SHOW_DETAILS = "showDetails";
114 + private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
115 + private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
116 + private static final String UPDATE_INSTANCE = "updateInstance";
117 +
118 + // fields
119 + private static final String ID = "id";
120 + private static final String IDS = "ids";
121 + private static final String HOVER = "hover";
122 + private static final String DEVICE = "device";
123 + private static final String HOST = "host";
124 + private static final String CLASS = "class";
125 + private static final String UNKNOWN = "unknown";
126 + private static final String ONE = "one";
127 + private static final String TWO = "two";
128 + private static final String SRC = "src";
129 + private static final String DST = "dst";
130 + private static final String DATA = "data";
131 + private static final String NAME = "name";
132 + private static final String NAMES = "names";
133 + private static final String ACTIVATE = "activate";
134 + private static final String DEACTIVATE = "deactivate";
135 + private static final String PRIMARY = "primary";
136 + private static final String SECONDARY = "secondary";
137 +
110 138
111 private static final String APP_ID = "org.onosproject.gui"; 139 private static final String APP_ID = "org.onosproject.gui";
112 140
...@@ -244,8 +272,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -244,8 +272,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
244 272
245 @Override 273 @Override
246 public void process(long sid, ObjectNode payload) { 274 public void process(long sid, ObjectNode payload) {
247 - String deact = string(payload, "deactivate"); 275 + String deact = string(payload, DEACTIVATE);
248 - String act = string(payload, "activate"); 276 + String act = string(payload, ACTIVATE);
249 overlayCache.switchOverlay(deact, act); 277 overlayCache.switchOverlay(deact, act);
250 } 278 }
251 } 279 }
...@@ -295,8 +323,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -295,8 +323,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
295 ObjectNode root = objectNode(); 323 ObjectNode root = objectNode();
296 ArrayNode names = arrayNode(); 324 ArrayNode names = arrayNode();
297 get(SpriteService.class).getNames().forEach(names::add); 325 get(SpriteService.class).getNames().forEach(names::add);
298 - root.set("names", names); 326 + root.set(NAMES, names);
299 - sendMessage("spriteListResponse", sid, root); 327 + sendMessage(SPRITE_LIST_RESPONSE, sid, root);
300 } 328 }
301 } 329 }
302 330
...@@ -307,10 +335,10 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -307,10 +335,10 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
307 335
308 @Override 336 @Override
309 public void process(long sid, ObjectNode payload) { 337 public void process(long sid, ObjectNode payload) {
310 - String name = string(payload, "name"); 338 + String name = string(payload, NAME);
311 ObjectNode root = objectNode(); 339 ObjectNode root = objectNode();
312 - root.set("data", get(SpriteService.class).get(name)); 340 + root.set(DATA, get(SpriteService.class).get(name));
313 - sendMessage("spriteDataResponse", sid, root); 341 + sendMessage(SPRITE_DATA_RESPONSE, sid, root);
314 } 342 }
315 } 343 }
316 344
...@@ -321,14 +349,20 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -321,14 +349,20 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
321 349
322 @Override 350 @Override
323 public void process(long sid, ObjectNode payload) { 351 public void process(long sid, ObjectNode payload) {
324 - String type = string(payload, "class", "unknown"); 352 + String type = string(payload, CLASS, UNKNOWN);
325 - String id = string(payload, "id"); 353 + String id = string(payload, ID);
326 - 354 + PropertyPanel pp = null;
327 - if (type.equals("device")) { 355 +
328 - sendMessage(deviceDetails(deviceId(id), sid)); 356 + if (type.equals(DEVICE)) {
329 - } else if (type.equals("host")) { 357 + pp = deviceDetails(deviceId(id), sid);
330 - sendMessage(hostDetails(hostId(id), sid)); 358 + overlayCache.currentOverlay().modifyDeviceDetails(pp);
359 + } else if (type.equals(HOST)) {
360 + pp = hostDetails(hostId(id), sid);
361 + overlayCache.currentOverlay().modifyHostDetails(pp);
331 } 362 }
363 +
364 + ObjectNode json = JsonUtils.envelope(SHOW_DETAILS, sid, json(pp));
365 + sendMessage(json);
332 } 366 }
333 } 367 }
334 368
...@@ -364,8 +398,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -364,8 +398,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
364 @Override 398 @Override
365 public void process(long sid, ObjectNode payload) { 399 public void process(long sid, ObjectNode payload) {
366 // TODO: add protection against device ids and non-existent hosts. 400 // TODO: add protection against device ids and non-existent hosts.
367 - HostId one = hostId(string(payload, "one")); 401 + HostId one = hostId(string(payload, ONE));
368 - HostId two = hostId(string(payload, "two")); 402 + HostId two = hostId(string(payload, TWO));
369 403
370 HostToHostIntent intent = HostToHostIntent.builder() 404 HostToHostIntent intent = HostToHostIntent.builder()
371 .appId(appId) 405 .appId(appId)
...@@ -386,8 +420,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -386,8 +420,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
386 @Override 420 @Override
387 public void process(long sid, ObjectNode payload) { 421 public void process(long sid, ObjectNode payload) {
388 // TODO: add protection against device ids and non-existent hosts. 422 // TODO: add protection against device ids and non-existent hosts.
389 - Set<HostId> src = getHostIds((ArrayNode) payload.path("src")); 423 + Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
390 - HostId dst = hostId(string(payload, "dst")); 424 + HostId dst = hostId(string(payload, DST));
391 Host dstHost = hostService.getHost(dst); 425 Host dstHost = hostService.getHost(dst);
392 426
393 Set<ConnectPoint> ingressPoints = getHostLocations(src); 427 Set<ConnectPoint> ingressPoints = getHostLocations(src);
...@@ -421,12 +455,12 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -421,12 +455,12 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
421 // Cancel any other traffic monitoring mode. 455 // Cancel any other traffic monitoring mode.
422 stopTrafficMonitoring(); 456 stopTrafficMonitoring();
423 457
424 - if (!payload.has("ids")) { 458 + if (!payload.has(IDS)) {
425 return; 459 return;
426 } 460 }
427 461
428 // Get the set of selected hosts and their intents. 462 // Get the set of selected hosts and their intents.
429 - ArrayNode ids = (ArrayNode) payload.path("ids"); 463 + ArrayNode ids = (ArrayNode) payload.path(IDS);
430 selectedHosts = getHosts(ids); 464 selectedHosts = getHosts(ids);
431 selectedDevices = getDevices(ids); 465 selectedDevices = getDevices(ids);
432 selectedIntents = intentFilter.findPathIntents( 466 selectedIntents = intentFilter.findPathIntents(
...@@ -435,7 +469,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -435,7 +469,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
435 469
436 if (haveSelectedIntents()) { 470 if (haveSelectedIntents()) {
437 // Send a message to highlight all links of all monitored intents. 471 // Send a message to highlight all links of all monitored intents.
438 - sendMessage(trafficMessage(new TrafficClass("primary", selectedIntents))); 472 + sendMessage(trafficMessage(new TrafficClass(PRIMARY, selectedIntents)));
439 } 473 }
440 474
441 // TODO: Re-introduce once the client click vs hover gesture stuff is sorted out. 475 // TODO: Re-introduce once the client click vs hover gesture stuff is sorted out.
...@@ -548,7 +582,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -548,7 +582,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
548 private synchronized void requestSummary(long sid) { 582 private synchronized void requestSummary(long sid) {
549 PropertyPanel pp = summmaryMessage(sid); 583 PropertyPanel pp = summmaryMessage(sid);
550 overlayCache.currentOverlay().modifySummary(pp); 584 overlayCache.currentOverlay().modifySummary(pp);
551 - ObjectNode json = JsonUtils.envelope("showSummary", sid, json(pp)); 585 + ObjectNode json = JsonUtils.envelope(SHOW_SUMMARY, sid, json(pp));
552 sendMessage(json); 586 sendMessage(json);
553 } 587 }
554 588
...@@ -668,12 +702,12 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -668,12 +702,12 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
668 startTrafficMonitoring(); 702 startTrafficMonitoring();
669 703
670 // Get the set of selected hosts and their intents. 704 // Get the set of selected hosts and their intents.
671 - ArrayNode ids = (ArrayNode) payload.path("ids"); 705 + ArrayNode ids = (ArrayNode) payload.path(IDS);
672 Set<Host> hosts = new HashSet<>(); 706 Set<Host> hosts = new HashSet<>();
673 Set<Device> devices = getDevices(ids); 707 Set<Device> devices = getDevices(ids);
674 708
675 // If there is a hover node, include it in the hosts and find intents. 709 // If there is a hover node, include it in the hosts and find intents.
676 - String hover = JsonUtils.string(payload, "hover"); 710 + String hover = JsonUtils.string(payload, HOVER);
677 if (!isNullOrEmpty(hover)) { 711 if (!isNullOrEmpty(hover)) {
678 addHover(hosts, devices, hover); 712 addHover(hosts, devices, hover);
679 } 713 }
...@@ -699,8 +733,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -699,8 +733,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
699 secondary.removeAll(primary); 733 secondary.removeAll(primary);
700 734
701 // Send a message to highlight all links of all monitored intents. 735 // Send a message to highlight all links of all monitored intents.
702 - sendMessage(trafficMessage(new TrafficClass("primary", primary), 736 + sendMessage(trafficMessage(new TrafficClass(PRIMARY, primary),
703 - new TrafficClass("secondary", secondary))); 737 + new TrafficClass(SECONDARY, secondary)));
704 } 738 }
705 739
706 // Requests next or previous related intent. 740 // Requests next or previous related intent.
...@@ -720,7 +754,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -720,7 +754,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
720 // selected intent highlighted. 754 // selected intent highlighted.
721 private void sendSelectedIntent() { 755 private void sendSelectedIntent() {
722 Intent selectedIntent = selectedIntents.get(currentIntentIndex); 756 Intent selectedIntent = selectedIntents.get(currentIntentIndex);
723 - log.info("Requested next intent {}", selectedIntent.id()); 757 + log.debug("Requested next intent {}", selectedIntent.id());
724 758
725 Set<Intent> primary = new HashSet<>(); 759 Set<Intent> primary = new HashSet<>();
726 primary.add(selectedIntent); 760 primary.add(selectedIntent);
...@@ -729,8 +763,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -729,8 +763,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
729 secondary.remove(selectedIntent); 763 secondary.remove(selectedIntent);
730 764
731 // Send a message to highlight all links of the selected intent. 765 // Send a message to highlight all links of the selected intent.
732 - sendMessage(trafficMessage(new TrafficClass("primary", primary), 766 + sendMessage(trafficMessage(new TrafficClass(PRIMARY, primary),
733 - new TrafficClass("secondary", secondary))); 767 + new TrafficClass(SECONDARY, secondary)));
734 } 768 }
735 769
736 // Requests monitoring of traffic for the selected intent. 770 // Requests monitoring of traffic for the selected intent.
...@@ -740,13 +774,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -740,13 +774,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
740 currentIntentIndex = 0; 774 currentIntentIndex = 0;
741 } 775 }
742 Intent selectedIntent = selectedIntents.get(currentIntentIndex); 776 Intent selectedIntent = selectedIntents.get(currentIntentIndex);
743 - log.info("Requested traffic for selected {}", selectedIntent.id()); 777 + log.debug("Requested traffic for selected {}", selectedIntent.id());
744 778
745 Set<Intent> primary = new HashSet<>(); 779 Set<Intent> primary = new HashSet<>();
746 primary.add(selectedIntent); 780 primary.add(selectedIntent);
747 781
748 // Send a message to highlight all links of the selected intent. 782 // Send a message to highlight all links of the selected intent.
749 - sendMessage(trafficMessage(new TrafficClass("primary", primary, true))); 783 + sendMessage(trafficMessage(new TrafficClass(PRIMARY, primary, true)));
750 } 784 }
751 } 785 }
752 786
...@@ -805,7 +839,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -805,7 +839,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
805 @Override 839 @Override
806 public void event(MastershipEvent event) { 840 public void event(MastershipEvent event) {
807 msgSender.execute(() -> { 841 msgSender.execute(() -> {
808 - sendAllInstances("updateInstance"); 842 + sendAllInstances(UPDATE_INSTANCE);
809 Device device = deviceService.getDevice(event.subject()); 843 Device device = deviceService.getDevice(event.subject());
810 if (device != null) { 844 if (device != null) {
811 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device))); 845 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
......
...@@ -440,57 +440,61 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -440,57 +440,61 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
440 JsonUtils.node(payload, "memento")); 440 JsonUtils.node(payload, "memento"));
441 } 441 }
442 442
443 - // Returns summary response. 443 + // -----------------------------------------------------------------------
444 + // Create models of the data to return, that overlays can adjust / augment
445 +
446 + // Returns property panel model for summary response.
444 protected PropertyPanel summmaryMessage(long sid) { 447 protected PropertyPanel summmaryMessage(long sid) {
445 Topology topology = topologyService.currentTopology(); 448 Topology topology = topologyService.currentTopology();
446 PropertyPanel pp = new PropertyPanel("ONOS Summary", "node") 449 PropertyPanel pp = new PropertyPanel("ONOS Summary", "node")
447 - .add(new PropertyPanel.Prop("Devices", format(topology.deviceCount()))) 450 + .add(new PropertyPanel.Prop("Devices", topology.deviceCount()))
448 - .add(new PropertyPanel.Prop("Links", format(topology.linkCount()))) 451 + .add(new PropertyPanel.Prop("Links", topology.linkCount()))
449 - .add(new PropertyPanel.Prop("Hosts", format(hostService.getHostCount()))) 452 + .add(new PropertyPanel.Prop("Hosts", hostService.getHostCount()))
450 - .add(new PropertyPanel.Prop("Topology SCCs", format(topology.clusterCount()))) 453 + .add(new PropertyPanel.Prop("Topology SCCs", topology.clusterCount()))
451 .add(new PropertyPanel.Separator()) 454 .add(new PropertyPanel.Separator())
452 - .add(new PropertyPanel.Prop("Intents", format(intentService.getIntentCount()))) 455 + .add(new PropertyPanel.Prop("Intents", intentService.getIntentCount()))
453 - .add(new PropertyPanel.Prop("Tunnels", format(tunnelService.tunnelCount()))) 456 + .add(new PropertyPanel.Prop("Tunnels", tunnelService.tunnelCount()))
454 - .add(new PropertyPanel.Prop("Flows", format(flowService.getFlowRuleCount()))) 457 + .add(new PropertyPanel.Prop("Flows", flowService.getFlowRuleCount()))
455 .add(new PropertyPanel.Prop("Version", version)); 458 .add(new PropertyPanel.Prop("Version", version));
456 459
457 return pp; 460 return pp;
458 } 461 }
459 462
460 - // Returns device details response. 463 + // Returns property panel model for device details response.
461 - protected ObjectNode deviceDetails(DeviceId deviceId, long sid) { 464 + protected PropertyPanel deviceDetails(DeviceId deviceId, long sid) {
462 Device device = deviceService.getDevice(deviceId); 465 Device device = deviceService.getDevice(deviceId);
463 Annotations annot = device.annotations(); 466 Annotations annot = device.annotations();
464 String name = annot.value(AnnotationKeys.NAME); 467 String name = annot.value(AnnotationKeys.NAME);
465 int portCount = deviceService.getPorts(deviceId).size(); 468 int portCount = deviceService.getPorts(deviceId).size();
466 int flowCount = getFlowCount(deviceId); 469 int flowCount = getFlowCount(deviceId);
467 int tunnelCount = getTunnelCount(deviceId); 470 int tunnelCount = getTunnelCount(deviceId);
468 - return JsonUtils.envelope("showDetails", sid, 471 +
469 - json(isNullOrEmpty(name) ? deviceId.toString() : name, 472 + String title = isNullOrEmpty(name) ? deviceId.toString() : name;
470 - device.type().toString().toLowerCase(), 473 + String typeId = device.type().toString().toLowerCase();
471 - new Prop("URI", deviceId.toString()), 474 +
472 - new Prop("Vendor", device.manufacturer()), 475 + PropertyPanel pp = new PropertyPanel(title, typeId)
473 - new Prop("H/W Version", device.hwVersion()), 476 + .id(deviceId.toString())
474 - new Prop("S/W Version", device.swVersion()), 477 + .add(new PropertyPanel.Prop("URI", deviceId.toString()))
475 - new Prop("Serial Number", device.serialNumber()), 478 + .add(new PropertyPanel.Prop("Vendor", device.manufacturer()))
476 - new Prop("Protocol", annot.value(AnnotationKeys.PROTOCOL)), 479 + .add(new PropertyPanel.Prop("H/W Version", device.hwVersion()))
477 - new Separator(), 480 + .add(new PropertyPanel.Prop("S/W Version", device.swVersion()))
478 - new Prop("Master", master(deviceId)), 481 + .add(new PropertyPanel.Prop("Serial Number", device.serialNumber()))
479 - new Prop("Latitude", annot.value(AnnotationKeys.LATITUDE)), 482 + .add(new PropertyPanel.Prop("Protocol", annot.value(AnnotationKeys.PROTOCOL)))
480 - new Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE)), 483 + .add(new PropertyPanel.Separator())
481 - new Separator(), 484 + .add(new PropertyPanel.Prop("Latitude", annot.value(AnnotationKeys.LATITUDE)))
482 - new Prop("Ports", Integer.toString(portCount)), 485 + .add(new PropertyPanel.Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE)))
483 - new Prop("Flows", Integer.toString(flowCount)), 486 + .add(new PropertyPanel.Separator())
484 - new Prop("Tunnels", Integer.toString(tunnelCount)) 487 + .add(new PropertyPanel.Prop("Ports", portCount))
485 - )); 488 + .add(new PropertyPanel.Prop("Flows", flowCount))
489 + .add(new PropertyPanel.Prop("Tunnels", tunnelCount));
490 +
491 + return pp;
486 } 492 }
487 493
488 protected int getFlowCount(DeviceId deviceId) { 494 protected int getFlowCount(DeviceId deviceId) {
489 int count = 0; 495 int count = 0;
490 - Iterator<FlowEntry> it = flowService.getFlowEntries(deviceId).iterator(); 496 + for (FlowEntry flowEntry : flowService.getFlowEntries(deviceId)) {
491 - while (it.hasNext()) {
492 count++; 497 count++;
493 - it.next();
494 } 498 }
495 return count; 499 return count;
496 } 500 }
...@@ -503,8 +507,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -503,8 +507,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
503 OpticalTunnelEndPoint dst = (OpticalTunnelEndPoint) tunnel.dst(); 507 OpticalTunnelEndPoint dst = (OpticalTunnelEndPoint) tunnel.dst();
504 DeviceId srcDevice = (DeviceId) src.elementId().get(); 508 DeviceId srcDevice = (DeviceId) src.elementId().get();
505 DeviceId dstDevice = (DeviceId) dst.elementId().get(); 509 DeviceId dstDevice = (DeviceId) dst.elementId().get();
506 - if (srcDevice.toString().equals(deviceId.toString()) 510 + if (srcDevice.toString().equals(deviceId.toString()) ||
507 - || dstDevice.toString().equals(deviceId.toString())) { 511 + dstDevice.toString().equals(deviceId.toString())) {
508 count++; 512 count++;
509 } 513 }
510 } 514 }
...@@ -516,9 +520,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -516,9 +520,8 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
516 List<FlowEntry> entries = new ArrayList<>(); 520 List<FlowEntry> entries = new ArrayList<>();
517 Set<Link> links = new HashSet<>(linkService.getDeviceEgressLinks(deviceId)); 521 Set<Link> links = new HashSet<>(linkService.getDeviceEgressLinks(deviceId));
518 Set<Host> hosts = hostService.getConnectedHosts(deviceId); 522 Set<Host> hosts = hostService.getConnectedHosts(deviceId);
519 - Iterator<FlowEntry> it = flowService.getFlowEntries(deviceId).iterator(); 523 + for (FlowEntry flowEntry : flowService.getFlowEntries(deviceId)) {
520 - while (it.hasNext()) { 524 + entries.add(flowEntry);
521 - entries.add(it.next());
522 } 525 }
523 526
524 // Add all edge links to the set 527 // Add all edge links to the set
...@@ -555,24 +558,30 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -555,24 +558,30 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
555 558
556 559
557 // Returns host details response. 560 // Returns host details response.
558 - protected ObjectNode hostDetails(HostId hostId, long sid) { 561 + protected PropertyPanel hostDetails(HostId hostId, long sid) {
559 Host host = hostService.getHost(hostId); 562 Host host = hostService.getHost(hostId);
560 Annotations annot = host.annotations(); 563 Annotations annot = host.annotations();
561 String type = annot.value(AnnotationKeys.TYPE); 564 String type = annot.value(AnnotationKeys.TYPE);
562 String name = annot.value(AnnotationKeys.NAME); 565 String name = annot.value(AnnotationKeys.NAME);
563 String vlan = host.vlan().toString(); 566 String vlan = host.vlan().toString();
564 - return JsonUtils.envelope("showDetails", sid, 567 +
565 - json(isNullOrEmpty(name) ? hostId.toString() : name, 568 + String title = isNullOrEmpty(name) ? hostId.toString() : name;
566 - isNullOrEmpty(type) ? "endstation" : type, 569 + String typeId = isNullOrEmpty(type) ? "endstation" : type;
567 - new Prop("MAC", host.mac().toString()), 570 +
568 - new Prop("IP", host.ipAddresses().toString().replaceAll("[\\[\\]]", "")), 571 + PropertyPanel pp = new PropertyPanel(title, typeId)
569 - new Prop("VLAN", vlan.equals("-1") ? "none" : vlan), 572 + .id(hostId.toString())
570 - new Separator(), 573 + .add(new PropertyPanel.Prop("MAC", host.mac().toString()))
571 - new Prop("Latitude", annot.value(AnnotationKeys.LATITUDE)), 574 + .add(new PropertyPanel.Prop("IP", host.ipAddresses().toString().replaceAll("[\\[\\]]", "")))
572 - new Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE)))); 575 + .add(new PropertyPanel.Prop("VLAN", vlan.equals("-1") ? "none" : vlan))
576 + .add(new PropertyPanel.Separator())
577 + .add(new PropertyPanel.Prop("Latitude", annot.value(AnnotationKeys.LATITUDE)))
578 + .add(new PropertyPanel.Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE)));
579 +
580 + return pp;
573 } 581 }
574 582
575 583
584 + // TODO: migrate to Traffic overlay
576 // Produces JSON message to trigger flow traffic overview visualization 585 // Produces JSON message to trigger flow traffic overview visualization
577 protected ObjectNode trafficSummaryMessage(StatsType type) { 586 protected ObjectNode trafficSummaryMessage(StatsType type) {
578 ObjectNode payload = objectNode(); 587 ObjectNode payload = objectNode();
...@@ -827,21 +836,19 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -827,21 +836,19 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
827 return format.format(value) + " " + unit; 836 return format.format(value) + " " + unit;
828 } 837 }
829 838
830 - // Formats the given number into a string.
831 - private String format(Number number) {
832 - DecimalFormat format = new DecimalFormat("#,###");
833 - return format.format(number);
834 - }
835 -
836 // Produces compact string representation of a link. 839 // Produces compact string representation of a link.
837 private static String compactLinkString(Link link) { 840 private static String compactLinkString(Link link) {
838 return String.format(COMPACT, link.src().elementId(), link.src().port(), 841 return String.format(COMPACT, link.src().elementId(), link.src().port(),
839 link.dst().elementId(), link.dst().port()); 842 link.dst().elementId(), link.dst().port());
840 } 843 }
841 844
845 + // translates the property panel into JSON, for returning to the client
842 protected ObjectNode json(PropertyPanel pp) { 846 protected ObjectNode json(PropertyPanel pp) {
843 ObjectNode result = objectNode() 847 ObjectNode result = objectNode()
844 - .put("title", pp.title()).put("type", pp.typeId()); 848 + .put("title", pp.title())
849 + .put("type", pp.typeId())
850 + .put("id", pp.id());
851 +
845 ObjectNode pnode = objectNode(); 852 ObjectNode pnode = objectNode();
846 ArrayNode porder = arrayNode(); 853 ArrayNode porder = arrayNode();
847 for (PropertyPanel.Prop p : pp.properties()) { 854 for (PropertyPanel.Prop p : pp.properties()) {
......
...@@ -219,6 +219,11 @@ ...@@ -219,6 +219,11 @@
219 // === ----------------------------------------------------- 219 // === -----------------------------------------------------
220 // Functions for populating the detail panel 220 // Functions for populating the detail panel
221 221
222 + var isDevice = {
223 + switch: 1,
224 + roadm: 1
225 + };
226 +
222 function displaySingle(data) { 227 function displaySingle(data) {
223 detail.setup(); 228 detail.setup();
224 229
...@@ -228,16 +233,21 @@ ...@@ -228,16 +233,21 @@
228 title = detail.appendHeader('h2') 233 title = detail.appendHeader('h2')
229 .classed('clickable', true), 234 .classed('clickable', true),
230 table = detail.appendBody('table'), 235 table = detail.appendBody('table'),
231 - tbody = table.append('tbody'); 236 + tbody = table.append('tbody'),
237 + navFn;
232 238
233 gs.addGlyph(svg, (data.type || 'unknown'), 40); 239 gs.addGlyph(svg, (data.type || 'unknown'), 40);
234 - title.text(data.id); 240 + title.text(data.title);
235 - svg.on('click', function () { 241 +
236 - ns.navTo(devPath, { devId: data.id }); 242 + // only add navigation when displaying a device
237 - }); 243 + if (isDevice[data.type]) {
238 - title.on('click', function () { 244 + navFn = function () {
239 - ns.navTo(devPath, { devId: data.id }); 245 + ns.navTo(devPath, { devId: data.id });
240 - }); 246 + };
247 +
248 + svg.on('click', navFn);
249 + title.on('click', navFn);
250 + }
241 251
242 listProps(tbody, data); 252 listProps(tbody, data);
243 addBtnFooter(); 253 addBtnFooter();
......