Simon Hunt
Committed by Gerrit Code Review

ONOS-2186 - GUI Topo Overlay - (WIP)

- Re-worked JSONification of LinkHighlights to simplify code.
- added a couple of static imports to clean up code.

Change-Id: Ia210c17dfb10972b52241b7a01c0906eef0a1f2a
...@@ -53,12 +53,11 @@ import org.onosproject.net.intent.IntentListener; ...@@ -53,12 +53,11 @@ import org.onosproject.net.intent.IntentListener;
53 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 53 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
54 import org.onosproject.net.link.LinkEvent; 54 import org.onosproject.net.link.LinkEvent;
55 import org.onosproject.net.link.LinkListener; 55 import org.onosproject.net.link.LinkListener;
56 -import org.onosproject.ui.JsonUtils;
57 import org.onosproject.ui.RequestHandler; 56 import org.onosproject.ui.RequestHandler;
58 import org.onosproject.ui.UiConnection; 57 import org.onosproject.ui.UiConnection;
59 import org.onosproject.ui.impl.TrafficMonitor.Mode; 58 import org.onosproject.ui.impl.TrafficMonitor.Mode;
60 -import org.onosproject.ui.topo.NodeSelection;
61 import org.onosproject.ui.topo.Highlights; 59 import org.onosproject.ui.topo.Highlights;
60 +import org.onosproject.ui.topo.NodeSelection;
62 import org.onosproject.ui.topo.PropertyPanel; 61 import org.onosproject.ui.topo.PropertyPanel;
63 62
64 import java.util.ArrayList; 63 import java.util.ArrayList;
...@@ -80,6 +79,8 @@ import static org.onosproject.net.HostId.hostId; ...@@ -80,6 +79,8 @@ import static org.onosproject.net.HostId.hostId;
80 import static org.onosproject.net.device.DeviceEvent.Type.*; 79 import static org.onosproject.net.device.DeviceEvent.Type.*;
81 import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; 80 import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
82 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; 81 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
82 +import static org.onosproject.ui.JsonUtils.envelope;
83 +import static org.onosproject.ui.impl.topo.TopoJson.json;
83 84
84 /** 85 /**
85 * Web socket capable of interacting with the GUI topology view. 86 * Web socket capable of interacting with the GUI topology view.
...@@ -349,8 +350,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -349,8 +350,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
349 overlayCache.currentOverlay().modifyHostDetails(pp); 350 overlayCache.currentOverlay().modifyHostDetails(pp);
350 } 351 }
351 352
352 - ObjectNode json = JsonUtils.envelope(SHOW_DETAILS, sid, json(pp)); 353 + sendMessage(envelope(SHOW_DETAILS, sid, json(pp)));
353 - sendMessage(json);
354 } 354 }
355 } 355 }
356 356
...@@ -538,7 +538,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -538,7 +538,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
538 538
539 // Converts highlights to JSON format and sends the message to the client 539 // Converts highlights to JSON format and sends the message to the client
540 protected void sendHighlights(Highlights highlights) { 540 protected void sendHighlights(Highlights highlights) {
541 - sendMessage(JsonUtils.envelope(SHOW_HIGHLIGHTS, json(highlights))); 541 + sendMessage(envelope(SHOW_HIGHLIGHTS, json(highlights)));
542 } 542 }
543 543
544 // Sends the specified data to the client. 544 // Sends the specified data to the client.
...@@ -553,8 +553,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -553,8 +553,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
553 private synchronized void requestSummary(long sid) { 553 private synchronized void requestSummary(long sid) {
554 PropertyPanel pp = summmaryMessage(sid); 554 PropertyPanel pp = summmaryMessage(sid);
555 overlayCache.currentOverlay().modifySummary(pp); 555 overlayCache.currentOverlay().modifySummary(pp);
556 - ObjectNode json = JsonUtils.envelope(SHOW_SUMMARY, sid, json(pp)); 556 + sendMessage(envelope(SHOW_SUMMARY, sid, json(pp)));
557 - sendMessage(json);
558 } 557 }
559 558
560 559
......
...@@ -63,11 +63,6 @@ import org.onosproject.ui.JsonUtils; ...@@ -63,11 +63,6 @@ import org.onosproject.ui.JsonUtils;
63 import org.onosproject.ui.UiConnection; 63 import org.onosproject.ui.UiConnection;
64 import org.onosproject.ui.UiMessageHandler; 64 import org.onosproject.ui.UiMessageHandler;
65 import org.onosproject.ui.impl.topo.ServicesBundle; 65 import org.onosproject.ui.impl.topo.ServicesBundle;
66 -import org.onosproject.ui.topo.ButtonId;
67 -import org.onosproject.ui.topo.DeviceHighlight;
68 -import org.onosproject.ui.topo.Highlights;
69 -import org.onosproject.ui.topo.HostHighlight;
70 -import org.onosproject.ui.topo.LinkHighlight;
71 import org.onosproject.ui.topo.PropertyPanel; 66 import org.onosproject.ui.topo.PropertyPanel;
72 import org.slf4j.Logger; 67 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory; 68 import org.slf4j.LoggerFactory;
...@@ -96,9 +91,9 @@ import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; ...@@ -96,9 +91,9 @@ import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
96 import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED; 91 import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
97 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; 92 import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
98 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; 93 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
99 -import static org.onosproject.ui.topo.TopoUtils.compactLinkString;
100 import static org.onosproject.ui.topo.TopoConstants.CoreButtons; 94 import static org.onosproject.ui.topo.TopoConstants.CoreButtons;
101 import static org.onosproject.ui.topo.TopoConstants.Properties; 95 import static org.onosproject.ui.topo.TopoConstants.Properties;
96 +import static org.onosproject.ui.topo.TopoUtils.compactLinkString;
102 97
103 /** 98 /**
104 * Facility for creating messages bound for the topology viewer. 99 * Facility for creating messages bound for the topology viewer.
...@@ -511,118 +506,4 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -511,118 +506,4 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
511 return pp; 506 return pp;
512 } 507 }
513 508
514 -
515 - // ----------------------------------------------------------------------
516 -
517 - /**
518 - * Transforms the given highlights model into a JSON message payload.
519 - *
520 - * @param highlights the model to transform
521 - * @return JSON payload
522 - */
523 - protected ObjectNode json(Highlights highlights) {
524 - ObjectNode payload = objectNode();
525 -
526 - ArrayNode devices = arrayNode();
527 - ArrayNode hosts = arrayNode();
528 - ArrayNode links = arrayNode();
529 -
530 - payload.set("devices", devices);
531 - payload.set("hosts", hosts);
532 - payload.set("links", links);
533 -
534 - highlights.devices().forEach(dh -> devices.add(json(dh)));
535 - highlights.hosts().forEach(hh -> hosts.add(json(hh)));
536 - jsonifyLinks(links, highlights.links());
537 -
538 - return payload;
539 - }
540 -
541 - private void jsonifyLinks(ArrayNode links, Set<LinkHighlight> hilites) {
542 - // a little more complicated than devices or hosts, since we are
543 - // grouping the link highlights by CSS classes
544 -
545 - // TODO: refactor this method (including client side) to use new format
546 - // as a more compact representation of the data...
547 - // * links:
548 - // * "primary animated":
549 - // * "link01" -> "label"
550 - // * "link02" -> "label"
551 - // * "secondary":
552 - // * "link04" -> "label"
553 - // * "link05" -> ""
554 -
555 -
556 - Map<String, List<String>> linkIdMap = new HashMap<>();
557 - Map<String, List<String>> linkLabelMap = new HashMap<>();
558 - List<String> ids;
559 - List<String> labels;
560 -
561 - for (LinkHighlight lh : hilites) {
562 - String cls = lh.cssClasses();
563 - ids = linkIdMap.get(cls);
564 - labels = linkLabelMap.get(cls);
565 -
566 - if (ids == null) { // labels will be null also
567 - ids = new ArrayList<>();
568 - linkIdMap.put(cls, ids);
569 - labels = new ArrayList<>();
570 - linkLabelMap.put(cls, labels);
571 - }
572 -
573 - ids.add(lh.elementId());
574 - labels.add(lh.label());
575 - }
576 -
577 - for (String cls : linkIdMap.keySet()) {
578 - ObjectNode group = objectNode();
579 - links.add(group);
580 -
581 - group.put("class", cls);
582 -
583 - ArrayNode lnks = arrayNode();
584 - ArrayNode labs = arrayNode();
585 - group.set("links", lnks);
586 - group.set("labels", labs);
587 -
588 - linkIdMap.get(cls).forEach(lnks::add);
589 - linkLabelMap.get(cls).forEach(labs::add);
590 - }
591 - }
592 -
593 -
594 - protected ObjectNode json(DeviceHighlight dh) {
595 - // TODO: implement this once we know what a device highlight looks like
596 - return objectNode();
597 - }
598 -
599 - protected ObjectNode json(HostHighlight hh) {
600 - // TODO: implement this once we know what a host highlight looks like
601 - return objectNode();
602 - }
603 -
604 - // translates the property panel into JSON, for returning to the client
605 - protected ObjectNode json(PropertyPanel pp) {
606 - ObjectNode result = objectNode()
607 - .put("title", pp.title())
608 - .put("type", pp.typeId())
609 - .put("id", pp.id());
610 -
611 - ObjectNode pnode = objectNode();
612 - ArrayNode porder = arrayNode();
613 - for (PropertyPanel.Prop p : pp.properties()) {
614 - porder.add(p.key());
615 - pnode.put(p.key(), p.value());
616 - }
617 - result.set("propOrder", porder);
618 - result.set("props", pnode);
619 -
620 - ArrayNode buttons = arrayNode();
621 - for (ButtonId b : pp.buttons()) {
622 - buttons.add(b.id());
623 - }
624 - result.set("buttons", buttons);
625 - return result;
626 - }
627 -
628 } 509 }
......
1 +/*
2 + * Copyright 2015 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 +
18 +package org.onosproject.ui.impl.topo;
19 +
20 +import com.fasterxml.jackson.databind.ObjectMapper;
21 +import com.fasterxml.jackson.databind.node.ArrayNode;
22 +import com.fasterxml.jackson.databind.node.ObjectNode;
23 +import org.onosproject.ui.topo.ButtonId;
24 +import org.onosproject.ui.topo.DeviceHighlight;
25 +import org.onosproject.ui.topo.Highlights;
26 +import org.onosproject.ui.topo.HostHighlight;
27 +import org.onosproject.ui.topo.LinkHighlight;
28 +import org.onosproject.ui.topo.PropertyPanel;
29 +
30 +/**
31 + * JSON utilities for the Topology View.
32 + */
33 +public final class TopoJson {
34 + private static final String DEVICES = "devices";
35 + private static final String HOSTS = "hosts";
36 + private static final String LINKS = "links";
37 +
38 + private static final String ID = "id";
39 + private static final String LABEL = "label";
40 + private static final String CSS = "css";
41 +
42 + private static final String TITLE = "title";
43 + private static final String TYPE = "type";
44 + private static final String PROP_ORDER = "propOrder";
45 + private static final String PROPS = "props";
46 + private static final String BUTTONS = "buttons";
47 +
48 +
49 + private static final ObjectMapper MAPPER = new ObjectMapper();
50 +
51 + private static ObjectNode objectNode() {
52 + return MAPPER.createObjectNode();
53 + }
54 +
55 + private static ArrayNode arrayNode() {
56 + return MAPPER.createArrayNode();
57 + }
58 +
59 + // non-instantiable
60 + private TopoJson() { }
61 +
62 + /**
63 + * Transforms the given highlights model into a JSON message payload.
64 + *
65 + * @param highlights the model to transform
66 + * @return JSON payload
67 + */
68 + public static ObjectNode json(Highlights highlights) {
69 + ObjectNode payload = objectNode();
70 +
71 + ArrayNode devices = arrayNode();
72 + ArrayNode hosts = arrayNode();
73 + ArrayNode links = arrayNode();
74 +
75 + payload.set(DEVICES, devices);
76 + payload.set(HOSTS, hosts);
77 + payload.set(LINKS, links);
78 +
79 + highlights.devices().forEach(dh -> devices.add(json(dh)));
80 + highlights.hosts().forEach(hh -> hosts.add(json(hh)));
81 + highlights.links().forEach(lh -> links.add(json(lh)));
82 +
83 + return payload;
84 + }
85 +
86 + private static ObjectNode json(DeviceHighlight dh) {
87 + // TODO: implement this once we know what a device highlight looks like
88 + return objectNode();
89 + }
90 +
91 + private static ObjectNode json(HostHighlight hh) {
92 + // TODO: implement this once we know what a host highlight looks like
93 + return objectNode();
94 + }
95 +
96 + private static ObjectNode json(LinkHighlight lh) {
97 + return objectNode()
98 + .put(ID, lh.elementId())
99 + .put(LABEL, lh.label())
100 + .put(CSS, lh.cssClasses());
101 + }
102 +
103 + /**
104 + * Translates the given property panel into JSON, for returning
105 + * to the client.
106 + *
107 + * @param pp the property panel model
108 + * @return JSON payload
109 + */
110 + public static ObjectNode json(PropertyPanel pp) {
111 + ObjectNode result = objectNode()
112 + .put(TITLE, pp.title())
113 + .put(TYPE, pp.typeId())
114 + .put(ID, pp.id());
115 +
116 + ObjectNode pnode = objectNode();
117 + ArrayNode porder = arrayNode();
118 + for (PropertyPanel.Prop p : pp.properties()) {
119 + porder.add(p.key());
120 + pnode.put(p.key(), p.value());
121 + }
122 + result.set(PROP_ORDER, porder);
123 + result.set(PROPS, pnode);
124 +
125 + ArrayNode buttons = arrayNode();
126 + for (ButtonId b : pp.buttons()) {
127 + buttons.add(b.id());
128 + }
129 + result.set(BUTTONS, buttons);
130 + return result;
131 + }
132 +
133 +}
...@@ -293,7 +293,6 @@ ...@@ -293,7 +293,6 @@
293 tss = _tss_; 293 tss = _tss_;
294 } 294 }
295 295
296 - // TODO: refactor this (currently using showTraffic data structure)
297 function showHighlights(data) { 296 function showHighlights(data) {
298 /* 297 /*
299 API to topoForce 298 API to topoForce
...@@ -303,43 +302,39 @@ ...@@ -303,43 +302,39 @@
303 findLinkById( id ) 302 findLinkById( id )
304 */ 303 */
305 304
306 - var paths = data.links; 305 + // TODO: clear node highlighting
307 -
308 api.clearLinkTrafficStyle(); 306 api.clearLinkTrafficStyle();
309 api.removeLinkLabels(); 307 api.removeLinkLabels();
310 308
311 - // Now highlight all links in the paths payload, and attach 309 + // TODO: device and host highlights
312 - // labels to them, if they are defined. 310 +
313 - paths.forEach(function (p) { 311 + data.links.forEach(function (lnk) {
314 - var n = p.links.length, 312 + var ldata = api.findLinkById(lnk.id),
315 - i, ldata, lab, units, magnitude, portcls; 313 + lab = lnk.label,
316 - 314 + units, portcls, magnitude;
317 - for (i=0; i<n; i++) { 315 +
318 - ldata = api.findLinkById(p.links[i]); 316 + if (ldata && !ldata.el.empty()) {
319 - lab = p.labels[i]; 317 + ldata.el.classed(lnk.css, true);
320 - 318 + ldata.label = lab;
321 - if (ldata && !ldata.el.empty()) { 319 +
322 - ldata.el.classed(p.class, true); 320 + // inject additional styling for port-based traffic
323 - ldata.label = lab; 321 + if (fs.endsWith(lab, 'bps')) {
324 - 322 + units = lab.substring(lab.length-4);
325 - if (fs.endsWith(lab, 'bps')) { 323 + portcls = 'port-traffic-' + units;
326 - // inject additional styling for port-based traffic 324 +
327 - units = lab.substring(lab.length-4); 325 + // for GBps
328 - portcls = 'port-traffic-' + units; 326 + if (units.substring(0,1) === 'G') {
329 - 327 + magnitude = fs.parseBitRate(lab);
330 - // for GBps 328 + if (magnitude >= 9) {
331 - if (units.substring(0,1) === 'G') { 329 + portcls += '-choked'
332 - magnitude = fs.parseBitRate(lab);
333 - if (magnitude >= 9) {
334 - portcls += '-choked'
335 - }
336 } 330 }
337 - ldata.el.classed(portcls, true);
338 } 331 }
332 + ldata.el.classed(portcls, true);
339 } 333 }
340 } 334 }
341 }); 335 });
342 336
337 + // TODO: api.updateNodes()
343 api.updateLinks(); 338 api.updateLinks();
344 } 339 }
345 340
......
...@@ -211,6 +211,7 @@ ...@@ -211,6 +211,7 @@
211 // invoked from mouseover/mouseout and selection change 211 // invoked from mouseover/mouseout and selection change
212 requestTrafficForMode: requestTrafficForMode, 212 requestTrafficForMode: requestTrafficForMode,
213 213
214 + // TODO: these should move to new UI demo app
214 // invoked from buttons on detail (multi-select) panel 215 // invoked from buttons on detail (multi-select) panel
215 addHostIntent: addHostIntent, 216 addHostIntent: addHostIntent,
216 addMultiSourceIntent: addMultiSourceIntent 217 addMultiSourceIntent: addMultiSourceIntent
......