Simon Hunt
Committed by Gerrit Code Review

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

- Cleaning up PropertyPanel methods - overloading values (string, int, long, object)

Change-Id: I84c86a48de8a776b407982687bc02def18eaef61
...@@ -29,6 +29,8 @@ import java.util.Set; ...@@ -29,6 +29,8 @@ import java.util.Set;
29 */ 29 */
30 public class PropertyPanel { 30 public class PropertyPanel {
31 31
32 + private static final DecimalFormat DF0 = new DecimalFormat("#,###");
33 +
32 private String title; 34 private String title;
33 private String typeId; 35 private String typeId;
34 private String id; 36 private String id;
...@@ -47,28 +49,93 @@ public class PropertyPanel { ...@@ -47,28 +49,93 @@ public class PropertyPanel {
47 } 49 }
48 50
49 /** 51 /**
50 - * Adds a property to the panel. 52 + * Adds an ID field to the panel data, to be included in
53 + * the returned JSON data to the client.
51 * 54 *
52 - * @param p the property 55 + * @param id the identifier
53 * @return self, for chaining 56 * @return self, for chaining
54 */ 57 */
55 - public PropertyPanel add(Prop p) { 58 + public PropertyPanel id(String id) {
56 - properties.add(p); 59 + this.id = id;
57 return this; 60 return this;
58 } 61 }
59 62
60 /** 63 /**
61 - * Adds an ID field to the panel data, to be included in 64 + * Adds a property to the panel data.
62 - * the returned JSON data to the client.
63 * 65 *
64 - * @param id the identifier 66 + * @param key property key
67 + * @param value property value
65 * @return self, for chaining 68 * @return self, for chaining
66 */ 69 */
67 - public PropertyPanel id(String id) { 70 + public PropertyPanel addProp(String key, String value) {
68 - this.id = id; 71 + properties.add(new Prop(key, value));
69 return this; 72 return this;
70 } 73 }
71 74
75 + /**
76 + * Adds a property to the panel data, using a decimal formatter.
77 + *
78 + * @param key property key
79 + * @param value property value
80 + * @return self, for chaining
81 + */
82 + public PropertyPanel addProp(String key, int value) {
83 + properties.add(new Prop(key, DF0.format(value)));
84 + return this;
85 + }
86 +
87 + /**
88 + * Adds a property to the panel data, using a decimal formatter.
89 + *
90 + * @param key property key
91 + * @param value property value
92 + * @return self, for chaining
93 + */
94 + public PropertyPanel addProp(String key, long value) {
95 + properties.add(new Prop(key, DF0.format(value)));
96 + return this;
97 + }
98 +
99 + /**
100 + * Adds a property to the panel data. Note that the value's
101 + * {@link Object#toString toString()} method is used to convert the
102 + * value to a string.
103 + *
104 + * @param key property key
105 + * @param value property value
106 + * @return self, for chaining
107 + */
108 + public PropertyPanel addProp(String key, Object value) {
109 + properties.add(new Prop(key, value.toString()));
110 + return this;
111 + }
112 +
113 + /**
114 + * Adds a property to the panel data. Note that the value's
115 + * {@link Object#toString toString()} method is used to convert the
116 + * value to a string, from which the characters defined in the given
117 + * regular expression string are stripped.
118 + *
119 + * @param key property key
120 + * @param value property value
121 + * @param reStrip regexp characters to strip from value string
122 + * @return self, for chaining
123 + */
124 + public PropertyPanel addProp(String key, Object value, String reStrip) {
125 + String val = value.toString().replaceAll(reStrip, "");
126 + properties.add(new Prop(key, val));
127 + return this;
128 + }
129 +
130 + /**
131 + * Adds a separator to the panel data.
132 + *
133 + * @return self, for chaining
134 + */
135 + public PropertyPanel addSeparator() {
136 + properties.add(new Separator());
137 + return this;
138 + }
72 139
73 /** 140 /**
74 * Returns the title text. 141 * Returns the title text.
...@@ -161,7 +228,6 @@ public class PropertyPanel { ...@@ -161,7 +228,6 @@ public class PropertyPanel {
161 228
162 // ==================== 229 // ====================
163 230
164 - private static final DecimalFormat DF0 = new DecimalFormat("#,###");
165 231
166 /** 232 /**
167 * Simple data carrier for a property, composed of a key/value pair. 233 * Simple data carrier for a property, composed of a key/value pair.
...@@ -182,26 +248,6 @@ public class PropertyPanel { ...@@ -182,26 +248,6 @@ public class PropertyPanel {
182 } 248 }
183 249
184 /** 250 /**
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 - /**
205 * Returns the property's key. 251 * Returns the property's key.
206 * 252 *
207 * @return the key 253 * @return the key
......
...@@ -17,12 +17,17 @@ ...@@ -17,12 +17,17 @@
17 17
18 package org.onosproject.ui.topo; 18 package org.onosproject.ui.topo;
19 19
20 +import org.junit.BeforeClass;
20 import org.junit.Test; 21 import org.junit.Test;
21 import org.onosproject.ui.topo.PropertyPanel.Prop; 22 import org.onosproject.ui.topo.PropertyPanel.Prop;
22 23
24 +import java.util.HashMap;
23 import java.util.Iterator; 25 import java.util.Iterator;
26 +import java.util.Map;
24 27
25 import static org.junit.Assert.assertEquals; 28 import static org.junit.Assert.assertEquals;
29 +import static org.junit.Assert.assertNull;
30 +import static org.junit.Assert.fail;
26 31
27 /** 32 /**
28 * Unit tests for {@link PropertyPanel}. 33 * Unit tests for {@link PropertyPanel}.
...@@ -33,20 +38,49 @@ public class PropertyPanelTest { ...@@ -33,20 +38,49 @@ public class PropertyPanelTest {
33 private static final String TYPE_ORIG = "Original type ID"; 38 private static final String TYPE_ORIG = "Original type ID";
34 private static final String TITLE_NEW = "New Title"; 39 private static final String TITLE_NEW = "New Title";
35 private static final String TYPE_NEW = "New type"; 40 private static final String TYPE_NEW = "New type";
41 + private static final String SOME_IDENTIFICATION = "It's Me!";
42 +
43 + private static final String KEY_A = "A";
44 + private static final String KEY_B = "B";
45 + private static final String KEY_C = "C";
46 + private static final String KEY_Z = "Z";
47 + private static final String VALUE_A = "Hay";
48 + private static final String VALUE_B = "Bee";
49 + private static final String VALUE_C = "Sea";
50 + private static final String VALUE_Z = "Zed";
51 +
52 + private static final Map<String, Prop> PROP_MAP = new HashMap<>();
53 +
54 + private static class FooClass {
55 + private final String s;
56 + FooClass(String s) {
57 + this.s = s;
58 + }
36 59
37 - private static final Prop PROP_A = new Prop("A", "Hay"); 60 + @Override
38 - private static final Prop PROP_B = new Prop("B", "Bee"); 61 + public String toString() {
39 - private static final Prop PROP_C = new Prop("C", "Sea"); 62 + return ">" + s + "<";
40 - private static final Prop PROP_Z = new Prop("Z", "Zed"); 63 + }
64 + }
41 65
42 private PropertyPanel pp; 66 private PropertyPanel pp;
43 67
44 68
69 +
70 + @BeforeClass
71 + public static void setUpClass() {
72 + PROP_MAP.put(KEY_A, new Prop(KEY_A, VALUE_A));
73 + PROP_MAP.put(KEY_B, new Prop(KEY_B, VALUE_B));
74 + PROP_MAP.put(KEY_C, new Prop(KEY_C, VALUE_C));
75 + PROP_MAP.put(KEY_Z, new Prop(KEY_Z, VALUE_Z));
76 + }
77 +
45 @Test 78 @Test
46 public void basic() { 79 public void basic() {
47 pp = new PropertyPanel(TITLE_ORIG, TYPE_ORIG); 80 pp = new PropertyPanel(TITLE_ORIG, TYPE_ORIG);
48 assertEquals("wrong title", TITLE_ORIG, pp.title()); 81 assertEquals("wrong title", TITLE_ORIG, pp.title());
49 assertEquals("wrong type", TYPE_ORIG, pp.typeId()); 82 assertEquals("wrong type", TYPE_ORIG, pp.typeId());
83 + assertNull("id?", pp.id());
50 assertEquals("unexpected props", 0, pp.properties().size()); 84 assertEquals("unexpected props", 0, pp.properties().size());
51 } 85 }
52 86
...@@ -64,20 +98,46 @@ public class PropertyPanelTest { ...@@ -64,20 +98,46 @@ public class PropertyPanelTest {
64 assertEquals("wrong type", TYPE_NEW, pp.typeId()); 98 assertEquals("wrong type", TYPE_NEW, pp.typeId());
65 } 99 }
66 100
67 - private void validateProps(Prop... props) { 101 + @Test
102 + public void setId() {
103 + basic();
104 + pp.id(SOME_IDENTIFICATION);
105 + assertEquals("wrong id", SOME_IDENTIFICATION, pp.id());
106 + }
107 +
108 + private void validateProps(String... keys) {
109 + Iterator<Prop> iter = pp.properties().iterator();
110 + for (String k: keys) {
111 + Prop exp = PROP_MAP.get(k);
112 + Prop act = iter.next();
113 + assertEquals("Bad prop sequence", exp, act);
114 + }
115 + }
116 +
117 + private void validateProp(String key, String expValue) {
68 Iterator<Prop> iter = pp.properties().iterator(); 118 Iterator<Prop> iter = pp.properties().iterator();
69 - for (Prop p: props) { 119 + Prop prop = null;
70 - Prop ppProp = iter.next(); 120 + while (iter.hasNext()) {
71 - assertEquals("Bad prop sequence", p, ppProp); 121 + Prop p = iter.next();
122 + if (p.key().equals(key)) {
123 + prop = p;
124 + break;
125 + }
126 + }
127 + if (prop == null) {
128 + fail("no prop found with key: " + key);
72 } 129 }
130 + assertEquals("Wrong prop value", expValue, prop.value());
73 } 131 }
74 132
75 @Test 133 @Test
76 public void props() { 134 public void props() {
77 basic(); 135 basic();
78 - pp.add(PROP_A).add(PROP_B).add(PROP_C); 136 + pp.addProp(KEY_A, VALUE_A)
137 + .addProp(KEY_B, VALUE_B)
138 + .addProp(KEY_C, VALUE_C);
79 assertEquals("bad props", 3, pp.properties().size()); 139 assertEquals("bad props", 3, pp.properties().size());
80 - validateProps(PROP_A, PROP_B, PROP_C); 140 + validateProps(KEY_A, KEY_B, KEY_C);
81 } 141 }
82 142
83 @Test 143 @Test
...@@ -91,8 +151,45 @@ public class PropertyPanelTest { ...@@ -91,8 +151,45 @@ public class PropertyPanelTest {
91 @Test 151 @Test
92 public void adjustProps() { 152 public void adjustProps() {
93 props(); 153 props();
94 - pp.removeProps("B", "A"); 154 + pp.removeProps(KEY_B, KEY_A);
95 - pp.add(PROP_Z); 155 + pp.addProp(KEY_Z, VALUE_Z);
96 - validateProps(PROP_C, PROP_Z); 156 + validateProps(KEY_C, KEY_Z);
97 } 157 }
158 +
159 + @Test
160 + public void intValues() {
161 + basic();
162 + pp.addProp(KEY_A, 200)
163 + .addProp(KEY_B, 2000)
164 + .addProp(KEY_C, 1234567);
165 +
166 + validateProp(KEY_A, "200");
167 + validateProp(KEY_B, "2,000");
168 + validateProp(KEY_C, "1,234,567");
169 + }
170 +
171 + @Test
172 + public void longValues() {
173 + basic();
174 + pp.addProp(KEY_A, 200L)
175 + .addProp(KEY_B, 2000L)
176 + .addProp(KEY_C, 1234567L)
177 + .addProp(KEY_Z, Long.MAX_VALUE);
178 +
179 + validateProp(KEY_A, "200");
180 + validateProp(KEY_B, "2,000");
181 + validateProp(KEY_C, "1,234,567");
182 + validateProp(KEY_Z, "9,223,372,036,854,775,807");
183 + }
184 +
185 + @Test
186 + public void objectValue() {
187 + basic();
188 + pp.addProp(KEY_A, new FooClass("a"))
189 + .addProp(KEY_B, new FooClass("bxyyzy"), "[xz]");
190 +
191 + validateProp(KEY_A, ">a<");
192 + validateProp(KEY_B, ">byyy<");
193 + }
194 +
98 } 195 }
......
...@@ -446,18 +446,17 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -446,18 +446,17 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
446 // Returns property panel model for summary response. 446 // Returns property panel model for summary response.
447 protected PropertyPanel summmaryMessage(long sid) { 447 protected PropertyPanel summmaryMessage(long sid) {
448 Topology topology = topologyService.currentTopology(); 448 Topology topology = topologyService.currentTopology();
449 - PropertyPanel pp = new PropertyPanel("ONOS Summary", "node")
450 - .add(new PropertyPanel.Prop("Devices", topology.deviceCount()))
451 - .add(new PropertyPanel.Prop("Links", topology.linkCount()))
452 - .add(new PropertyPanel.Prop("Hosts", hostService.getHostCount()))
453 - .add(new PropertyPanel.Prop("Topology SCCs", topology.clusterCount()))
454 - .add(new PropertyPanel.Separator())
455 - .add(new PropertyPanel.Prop("Intents", intentService.getIntentCount()))
456 - .add(new PropertyPanel.Prop("Tunnels", tunnelService.tunnelCount()))
457 - .add(new PropertyPanel.Prop("Flows", flowService.getFlowRuleCount()))
458 - .add(new PropertyPanel.Prop("Version", version));
459 449
460 - return pp; 450 + return new PropertyPanel("ONOS Summary", "node")
451 + .addProp("Devices", topology.deviceCount())
452 + .addProp("Links", topology.linkCount())
453 + .addProp("Hosts", hostService.getHostCount())
454 + .addProp("Topology SCCs", topology.clusterCount())
455 + .addSeparator()
456 + .addProp("Intents", intentService.getIntentCount())
457 + .addProp("Tunnels", tunnelService.tunnelCount())
458 + .addProp("Flows", flowService.getFlowRuleCount())
459 + .addProp("Version", version);
461 } 460 }
462 461
463 // Returns property panel model for device details response. 462 // Returns property panel model for device details response.
...@@ -474,19 +473,21 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -474,19 +473,21 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
474 473
475 PropertyPanel pp = new PropertyPanel(title, typeId) 474 PropertyPanel pp = new PropertyPanel(title, typeId)
476 .id(deviceId.toString()) 475 .id(deviceId.toString())
477 - .add(new PropertyPanel.Prop("URI", deviceId.toString())) 476 + .addProp("URI", deviceId.toString())
478 - .add(new PropertyPanel.Prop("Vendor", device.manufacturer())) 477 + .addProp("Vendor", device.manufacturer())
479 - .add(new PropertyPanel.Prop("H/W Version", device.hwVersion())) 478 + .addProp("H/W Version", device.hwVersion())
480 - .add(new PropertyPanel.Prop("S/W Version", device.swVersion())) 479 + .addProp("S/W Version", device.swVersion())
481 - .add(new PropertyPanel.Prop("Serial Number", device.serialNumber())) 480 + .addProp("Serial Number", device.serialNumber())
482 - .add(new PropertyPanel.Prop("Protocol", annot.value(AnnotationKeys.PROTOCOL))) 481 + .addProp("Protocol", annot.value(AnnotationKeys.PROTOCOL))
483 - .add(new PropertyPanel.Separator()) 482 + .addSeparator()
484 - .add(new PropertyPanel.Prop("Latitude", annot.value(AnnotationKeys.LATITUDE))) 483 + .addProp("Latitude", annot.value(AnnotationKeys.LATITUDE))
485 - .add(new PropertyPanel.Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE))) 484 + .addProp("Longitude", annot.value(AnnotationKeys.LONGITUDE))
486 - .add(new PropertyPanel.Separator()) 485 + .addSeparator()
487 - .add(new PropertyPanel.Prop("Ports", portCount)) 486 + .addProp("Ports", portCount)
488 - .add(new PropertyPanel.Prop("Flows", flowCount)) 487 + .addProp("Flows", flowCount)
489 - .add(new PropertyPanel.Prop("Tunnels", tunnelCount)); 488 + .addProp("Tunnels", tunnelCount);
489 +
490 + // TODO: add button descriptors
490 491
491 return pp; 492 return pp;
492 } 493 }
...@@ -570,13 +571,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -570,13 +571,14 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
570 571
571 PropertyPanel pp = new PropertyPanel(title, typeId) 572 PropertyPanel pp = new PropertyPanel(title, typeId)
572 .id(hostId.toString()) 573 .id(hostId.toString())
573 - .add(new PropertyPanel.Prop("MAC", host.mac().toString())) 574 + .addProp("MAC", host.mac())
574 - .add(new PropertyPanel.Prop("IP", host.ipAddresses().toString().replaceAll("[\\[\\]]", ""))) 575 + .addProp("IP", host.ipAddresses(), "[\\[\\]]")
575 - .add(new PropertyPanel.Prop("VLAN", vlan.equals("-1") ? "none" : vlan)) 576 + .addProp("VLAN", vlan.equals("-1") ? "none" : vlan)
576 - .add(new PropertyPanel.Separator()) 577 + .addSeparator()
577 - .add(new PropertyPanel.Prop("Latitude", annot.value(AnnotationKeys.LATITUDE))) 578 + .addProp("Latitude", annot.value(AnnotationKeys.LATITUDE))
578 - .add(new PropertyPanel.Prop("Longitude", annot.value(AnnotationKeys.LONGITUDE))); 579 + .addProp("Longitude", annot.value(AnnotationKeys.LONGITUDE));
579 - 580 +
581 + // TODO: add button descriptors
580 return pp; 582 return pp;
581 } 583 }
582 584
...@@ -860,21 +862,6 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -860,21 +862,6 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
860 return result; 862 return result;
861 } 863 }
862 864
863 - // Produces JSON property details.
864 - private ObjectNode json(String id, String type, Prop... props) {
865 - ObjectNode result = objectNode()
866 - .put("id", id).put("type", type);
867 - ObjectNode pnode = objectNode();
868 - ArrayNode porder = arrayNode();
869 - for (Prop p : props) {
870 - porder.add(p.key);
871 - pnode.put(p.key, p.value);
872 - }
873 - result.set("propOrder", porder);
874 - result.set("props", pnode);
875 - return result;
876 - }
877 -
878 // Produces canonical link key, i.e. one that will match link and its inverse. 865 // Produces canonical link key, i.e. one that will match link and its inverse.
879 static LinkKey canonicalLinkKey(Link link) { 866 static LinkKey canonicalLinkKey(Link link) {
880 String sn = link.src().elementId().toString(); 867 String sn = link.src().elementId().toString();
...@@ -946,25 +933,6 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -946,25 +933,6 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
946 } 933 }
947 } 934 }
948 935
949 - // Auxiliary key/value carrier.
950 - @Deprecated
951 - static class Prop {
952 - public final String key;
953 - public final String value;
954 -
955 - protected Prop(String key, String value) {
956 - this.key = key;
957 - this.value = value;
958 - }
959 - }
960 -
961 - // Auxiliary properties separator
962 - @Deprecated
963 - static class Separator extends Prop {
964 - protected Separator() {
965 - super("-", "");
966 - }
967 - }
968 936
969 // TODO: move this to traffic overlay component 937 // TODO: move this to traffic overlay component
970 // Auxiliary carrier of data for requesting traffic message. 938 // Auxiliary carrier of data for requesting traffic message.
......