ONOS-1479 - GUI Topology Overlay Work - (WIP)
- Augmented PropertyPanel class for more manipulation, and added unit tests. - Added TopoConstants. - Fixed bug in topoPanel.js that was not using the typeID from the event data. Change-Id: I7ad759217f2d32642a09be2a9199cf1fcb45ac6e
Showing
5 changed files
with
310 additions
and
10 deletions
... | @@ -17,8 +17,11 @@ | ... | @@ -17,8 +17,11 @@ |
17 | 17 | ||
18 | package org.onosproject.ui.topo; | 18 | package org.onosproject.ui.topo; |
19 | 19 | ||
20 | +import com.google.common.collect.Sets; | ||
21 | + | ||
20 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
21 | import java.util.List; | 23 | import java.util.List; |
24 | +import java.util.Set; | ||
22 | 25 | ||
23 | /** | 26 | /** |
24 | * Models a panel displayed on the Topology View. | 27 | * Models a panel displayed on the Topology View. |
... | @@ -29,59 +32,176 @@ public class PropertyPanel { | ... | @@ -29,59 +32,176 @@ public class PropertyPanel { |
29 | private String typeId; | 32 | private String typeId; |
30 | private List<Prop> properties = new ArrayList<>(); | 33 | private List<Prop> properties = new ArrayList<>(); |
31 | 34 | ||
32 | - | 35 | + /** |
36 | + * Constructs a property panel model with the given title and | ||
37 | + * type identifier (icon to display). | ||
38 | + * | ||
39 | + * @param title title text | ||
40 | + * @param typeId type (icon) ID | ||
41 | + */ | ||
33 | public PropertyPanel(String title, String typeId) { | 42 | public PropertyPanel(String title, String typeId) { |
34 | this.title = title; | 43 | this.title = title; |
35 | this.typeId = typeId; | 44 | this.typeId = typeId; |
36 | } | 45 | } |
37 | 46 | ||
47 | + /** | ||
48 | + * Adds a property to the panel. | ||
49 | + * | ||
50 | + * @param p the property | ||
51 | + * @return self, for chaining | ||
52 | + */ | ||
38 | public PropertyPanel add(Prop p) { | 53 | public PropertyPanel add(Prop p) { |
39 | properties.add(p); | 54 | properties.add(p); |
40 | return this; | 55 | return this; |
41 | } | 56 | } |
42 | 57 | ||
58 | + /** | ||
59 | + * Returns the title text. | ||
60 | + * | ||
61 | + * @return title text | ||
62 | + */ | ||
43 | public String title() { | 63 | public String title() { |
44 | return title; | 64 | return title; |
45 | } | 65 | } |
46 | 66 | ||
67 | + /** | ||
68 | + * Returns the type identifier. | ||
69 | + * | ||
70 | + * @return type identifier | ||
71 | + */ | ||
47 | public String typeId() { | 72 | public String typeId() { |
48 | return typeId; | 73 | return typeId; |
49 | } | 74 | } |
50 | 75 | ||
76 | + /** | ||
77 | + * Returns the list of properties to be displayed. | ||
78 | + * | ||
79 | + * @return the property list | ||
80 | + */ | ||
51 | // TODO: consider protecting this? | 81 | // TODO: consider protecting this? |
52 | public List<Prop> properties() { | 82 | public List<Prop> properties() { |
53 | return properties; | 83 | return properties; |
54 | } | 84 | } |
55 | 85 | ||
86 | + // == MUTATORS | ||
87 | + | ||
88 | + /** | ||
89 | + * Sets the title text. | ||
90 | + * | ||
91 | + * @param title title text | ||
92 | + * @return self, for chaining | ||
93 | + */ | ||
56 | public PropertyPanel title(String title) { | 94 | public PropertyPanel title(String title) { |
57 | this.title = title; | 95 | this.title = title; |
58 | return this; | 96 | return this; |
59 | } | 97 | } |
60 | 98 | ||
61 | - // TODO: add other builder-like setters here | 99 | + /** |
100 | + * Sets the type identifier (icon ID). | ||
101 | + * | ||
102 | + * @param typeId type identifier | ||
103 | + * @return self, for chaining | ||
104 | + */ | ||
105 | + public PropertyPanel typeId(String typeId) { | ||
106 | + this.typeId = typeId; | ||
107 | + return this; | ||
108 | + } | ||
62 | 109 | ||
110 | + /** | ||
111 | + * Removes properties with the given keys from the list. | ||
112 | + * | ||
113 | + * @param keys keys of properties to remove | ||
114 | + * @return self, for chaining | ||
115 | + */ | ||
116 | + public PropertyPanel removeProps(String... keys) { | ||
117 | + Set<String> keysForRemoval = Sets.newHashSet(keys); | ||
118 | + List<Prop> propsToKeep = new ArrayList<>(); | ||
119 | + for (Prop p: properties) { | ||
120 | + if (!keysForRemoval.contains(p.key())) { | ||
121 | + propsToKeep.add(p); | ||
122 | + } | ||
123 | + } | ||
124 | + properties = propsToKeep; | ||
125 | + return this; | ||
126 | + } | ||
127 | + | ||
128 | + /** | ||
129 | + * Removes all currently defined properties. | ||
130 | + * | ||
131 | + * @return self, for chaining | ||
132 | + */ | ||
133 | + public PropertyPanel removeAllProps() { | ||
134 | + properties.clear(); | ||
135 | + return this; | ||
136 | + } | ||
63 | 137 | ||
64 | // ==================== | 138 | // ==================== |
65 | 139 | ||
140 | + /** | ||
141 | + * Simple data carrier for a property, composed of a key/value pair. | ||
142 | + */ | ||
66 | public static class Prop { | 143 | public static class Prop { |
67 | - public final String key; | 144 | + private final String key; |
68 | - public final String value; | 145 | + private final String value; |
69 | - | 146 | + |
147 | + /** | ||
148 | + * Constructs a property data value. | ||
149 | + * | ||
150 | + * @param key property key | ||
151 | + * @param value property value | ||
152 | + */ | ||
70 | public Prop(String key, String value) { | 153 | public Prop(String key, String value) { |
71 | this.key = key; | 154 | this.key = key; |
72 | this.value = value; | 155 | this.value = value; |
73 | } | 156 | } |
74 | 157 | ||
158 | + /** | ||
159 | + * Returns the property's key. | ||
160 | + * | ||
161 | + * @return the key | ||
162 | + */ | ||
75 | public String key() { | 163 | public String key() { |
76 | return key; | 164 | return key; |
77 | } | 165 | } |
78 | 166 | ||
167 | + /** | ||
168 | + * Returns the property's value. | ||
169 | + * | ||
170 | + * @return the value | ||
171 | + */ | ||
79 | public String value() { | 172 | public String value() { |
80 | return value; | 173 | return value; |
81 | } | 174 | } |
175 | + | ||
176 | + @Override | ||
177 | + public boolean equals(Object o) { | ||
178 | + if (this == o) { | ||
179 | + return true; | ||
180 | + } | ||
181 | + if (o == null || getClass() != o.getClass()) { | ||
182 | + return false; | ||
183 | + } | ||
184 | + | ||
185 | + Prop prop = (Prop) o; | ||
186 | + return key.equals(prop.key) && value.equals(prop.value); | ||
187 | + } | ||
188 | + | ||
189 | + @Override | ||
190 | + public int hashCode() { | ||
191 | + int result = key.hashCode(); | ||
192 | + result = 31 * result + value.hashCode(); | ||
193 | + return result; | ||
194 | + } | ||
195 | + | ||
196 | + @Override | ||
197 | + public String toString() { | ||
198 | + return "{" + key + " -> " + value + "}"; | ||
199 | + } | ||
82 | } | 200 | } |
83 | 201 | ||
84 | - // Auxiliary properties separator | 202 | + /** |
203 | + * Auxiliary class representing a separator property. | ||
204 | + */ | ||
85 | public static class Separator extends Prop { | 205 | public static class Separator extends Prop { |
86 | public Separator() { | 206 | public Separator() { |
87 | super("-", ""); | 207 | super("-", ""); | ... | ... |
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.topo; | ||
19 | + | ||
20 | +/** | ||
21 | + * Defines string constants used in the Topology View of the ONOS GUI. | ||
22 | + * <p> | ||
23 | + * See also: | ||
24 | + * <ul> | ||
25 | + * <li> https://wiki.onosproject.org/display/ONOS/UI+Service+-+GlyphService </li> | ||
26 | + * </ul> | ||
27 | + */ | ||
28 | +public final class TopoConstants { | ||
29 | + | ||
30 | + /** | ||
31 | + * Defines constants for standard glyph identifiers. | ||
32 | + */ | ||
33 | + public static final class Glyphs { | ||
34 | + public static final String UNKNOWN = "unknown"; | ||
35 | + public static final String BIRD = "bird"; | ||
36 | + public static final String NODE = "node"; | ||
37 | + public static final String SWITCH = "switch"; | ||
38 | + public static final String ROADM = "roadm"; | ||
39 | + public static final String ENDSTATION = "endstation"; | ||
40 | + public static final String ROUTER = "router"; | ||
41 | + public static final String BGP_SPEAKER = "bgpSpeaker"; | ||
42 | + public static final String CHAIN = "chain"; | ||
43 | + public static final String CROWN = "crown"; | ||
44 | + public static final String TOPO = "topo"; | ||
45 | + public static final String REFRESH = "refresh"; | ||
46 | + public static final String GARBAGE = "garbage"; | ||
47 | + public static final String FLOW_TABLE = "flowTable"; | ||
48 | + public static final String PORT_TABLE = "portTable"; | ||
49 | + public static final String GROUP_TABLE = "groupTable"; | ||
50 | + public static final String SUMMARY = "summary"; | ||
51 | + public static final String DETAILS = "details"; | ||
52 | + public static final String PORTS = "ports"; | ||
53 | + public static final String MAP = "map"; | ||
54 | + public static final String CYCLE_LABELS = "cycleLabels"; | ||
55 | + public static final String OBLIQUE = "oblique"; | ||
56 | + public static final String FILTERS = "filters"; | ||
57 | + public static final String RESET_ZOOM = "resetZoom"; | ||
58 | + public static final String RELATED_INTENTS = "relatedIntents"; | ||
59 | + public static final String NEXT_INTENT = "nextIntent"; | ||
60 | + public static final String PREV_INTENT = "prevIntent"; | ||
61 | + public static final String INTENT_TRAFFIC = "intentTraffic"; | ||
62 | + public static final String ALL_TRAFFIC = "allTraffic"; | ||
63 | + public static final String FLOWS = "flows"; | ||
64 | + public static final String EQ_MASTER = "eqMaster"; | ||
65 | + public static final String UI_ATTACHED = "uiAttached"; | ||
66 | + public static final String CHECK_MARK = "checkMark"; | ||
67 | + public static final String X_MARK = "xMark"; | ||
68 | + public static final String TRIANGLE_UP = "triangleUp"; | ||
69 | + public static final String TRIANGLE_DOWN = "triangleDown"; | ||
70 | + public static final String PLUS = "plus"; | ||
71 | + public static final String MINUS = "minus"; | ||
72 | + public static final String PLAY = "play"; | ||
73 | + public static final String STOP = "stop"; | ||
74 | + public static final String CLOUD = "cloud"; | ||
75 | + } | ||
76 | +} |
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.topo; | ||
19 | + | ||
20 | +import org.junit.Test; | ||
21 | +import org.onosproject.ui.topo.PropertyPanel.Prop; | ||
22 | + | ||
23 | +import java.util.Iterator; | ||
24 | + | ||
25 | +import static org.junit.Assert.assertEquals; | ||
26 | + | ||
27 | +/** | ||
28 | + * Unit tests for {@link PropertyPanel}. | ||
29 | + */ | ||
30 | +public class PropertyPanelTest { | ||
31 | + | ||
32 | + private static final String TITLE_ORIG = "Original Title"; | ||
33 | + private static final String TYPE_ORIG = "Original type ID"; | ||
34 | + private static final String TITLE_NEW = "New Title"; | ||
35 | + private static final String TYPE_NEW = "New type"; | ||
36 | + | ||
37 | + private static final Prop PROP_A = new Prop("A", "Hay"); | ||
38 | + private static final Prop PROP_B = new Prop("B", "Bee"); | ||
39 | + private static final Prop PROP_C = new Prop("C", "Sea"); | ||
40 | + private static final Prop PROP_Z = new Prop("Z", "Zed"); | ||
41 | + | ||
42 | + private PropertyPanel pp; | ||
43 | + | ||
44 | + | ||
45 | + @Test | ||
46 | + public void basic() { | ||
47 | + pp = new PropertyPanel(TITLE_ORIG, TYPE_ORIG); | ||
48 | + assertEquals("wrong title", TITLE_ORIG, pp.title()); | ||
49 | + assertEquals("wrong type", TYPE_ORIG, pp.typeId()); | ||
50 | + assertEquals("unexpected props", 0, pp.properties().size()); | ||
51 | + } | ||
52 | + | ||
53 | + @Test | ||
54 | + public void changeTitle() { | ||
55 | + basic(); | ||
56 | + pp.title(TITLE_NEW); | ||
57 | + assertEquals("wrong title", TITLE_NEW, pp.title()); | ||
58 | + } | ||
59 | + | ||
60 | + @Test | ||
61 | + public void changeType() { | ||
62 | + basic(); | ||
63 | + pp.typeId(TYPE_NEW); | ||
64 | + assertEquals("wrong type", TYPE_NEW, pp.typeId()); | ||
65 | + } | ||
66 | + | ||
67 | + private void validateProps(Prop... props) { | ||
68 | + Iterator<Prop> iter = pp.properties().iterator(); | ||
69 | + for (Prop p: props) { | ||
70 | + Prop ppProp = iter.next(); | ||
71 | + assertEquals("Bad prop sequence", p, ppProp); | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + @Test | ||
76 | + public void props() { | ||
77 | + basic(); | ||
78 | + pp.add(PROP_A).add(PROP_B).add(PROP_C); | ||
79 | + assertEquals("bad props", 3, pp.properties().size()); | ||
80 | + validateProps(PROP_A, PROP_B, PROP_C); | ||
81 | + } | ||
82 | + | ||
83 | + @Test | ||
84 | + public void removeAllProps() { | ||
85 | + props(); | ||
86 | + assertEquals("wrong props", 3, pp.properties().size()); | ||
87 | + pp.removeAllProps(); | ||
88 | + assertEquals("unexpected props", 0, pp.properties().size()); | ||
89 | + } | ||
90 | + | ||
91 | + @Test | ||
92 | + public void adjustProps() { | ||
93 | + props(); | ||
94 | + pp.removeProps("B", "A"); | ||
95 | + pp.add(PROP_Z); | ||
96 | + validateProps(PROP_C, PROP_Z); | ||
97 | + } | ||
98 | +} |
... | @@ -28,6 +28,7 @@ import org.onosproject.ui.UiExtensionService; | ... | @@ -28,6 +28,7 @@ import org.onosproject.ui.UiExtensionService; |
28 | import org.onosproject.ui.UiMessageHandlerFactory; | 28 | import org.onosproject.ui.UiMessageHandlerFactory; |
29 | import org.onosproject.ui.UiMessageHandler; | 29 | import org.onosproject.ui.UiMessageHandler; |
30 | import org.onosproject.ui.UiTopoOverlayFactory; | 30 | import org.onosproject.ui.UiTopoOverlayFactory; |
31 | +import org.onosproject.ui.topo.TopoConstants; | ||
31 | import org.slf4j.Logger; | 32 | import org.slf4j.Logger; |
32 | import org.slf4j.LoggerFactory; | 33 | import org.slf4j.LoggerFactory; |
33 | 34 | ||
... | @@ -225,7 +226,8 @@ public class UiWebSocket | ... | @@ -225,7 +226,8 @@ public class UiWebSocket |
225 | ObjectNode instance = mapper.createObjectNode() | 226 | ObjectNode instance = mapper.createObjectNode() |
226 | .put("id", node.id().toString()) | 227 | .put("id", node.id().toString()) |
227 | .put("ip", node.ip().toString()) | 228 | .put("ip", node.ip().toString()) |
228 | - .put("uiAttached", node.equals(service.getLocalNode())); | 229 | + .put(TopoConstants.Glyphs.UI_ATTACHED, |
230 | + node.equals(service.getLocalNode())); | ||
229 | instances.add(instance); | 231 | instances.add(instance); |
230 | } | 232 | } |
231 | 233 | ... | ... |
... | @@ -203,10 +203,14 @@ | ... | @@ -203,10 +203,14 @@ |
203 | .append('svg'), | 203 | .append('svg'), |
204 | title = summary.appendHeader('h2'), | 204 | title = summary.appendHeader('h2'), |
205 | table = summary.appendBody('table'), | 205 | table = summary.appendBody('table'), |
206 | - tbody = table.append('tbody'); | 206 | + tbody = table.append('tbody'), |
207 | + glyphId = data.type || 'node'; | ||
207 | 208 | ||
208 | - gs.addGlyph(svg, 'node', 40); | 209 | + gs.addGlyph(svg, glyphId, 40); |
209 | - gs.addGlyph(svg, 'bird', 24, true, [8,12]); | 210 | + |
211 | + if (glyphId === 'node') { | ||
212 | + gs.addGlyph(svg, 'bird', 24, true, [8,12]); | ||
213 | + } | ||
210 | 214 | ||
211 | title.text(data.title); | 215 | title.text(data.title); |
212 | listProps(tbody, data); | 216 | listProps(tbody, data); | ... | ... |
-
Please register or login to post a comment