Thomas Vachuska
Committed by Gerrit Code Review

Enhanced layout service and hooked-in the ui topo session.

Change-Id: I357143766deb3f0d697a3e7963a53968ccdf3bc8
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.ui; 16 package org.onosproject.ui;
17 17
18 import com.fasterxml.jackson.databind.node.ObjectNode; 18 import com.fasterxml.jackson.databind.node.ObjectNode;
19 +import org.onosproject.ui.model.topo.UiTopoLayout;
19 20
20 /** 21 /**
21 * Abstraction of a user interface session connection. 22 * Abstraction of a user interface session connection.
...@@ -30,6 +31,34 @@ public interface UiConnection { ...@@ -30,6 +31,34 @@ public interface UiConnection {
30 String userName(); 31 String userName();
31 32
32 /** 33 /**
34 + * Returns the current layout context.
35 + *
36 + * @return current topology layout
37 + */
38 + UiTopoLayout currentLayout();
39 +
40 + /**
41 + * Changes the current layout context to the specified layout.
42 + *
43 + * @param topoLayout new topology layout context
44 + */
45 + void setCurrentLayout(UiTopoLayout topoLayout);
46 +
47 + /**
48 + * Returns the current view identifier.
49 + *
50 + * @return current view
51 + */
52 + String currentView();
53 +
54 + /**
55 + * Sets the currently selected view.
56 + *
57 + * @param viewId view identifier
58 + */
59 + void setCurrentView(String viewId);
60 +
61 + /**
33 * Sends the specified JSON message to the user interface client. 62 * Sends the specified JSON message to the user interface client.
34 * 63 *
35 * @param message message to send 64 * @param message message to send
......
...@@ -26,6 +26,14 @@ import java.util.Set; ...@@ -26,6 +26,14 @@ import java.util.Set;
26 public interface UiTopoLayoutService { 26 public interface UiTopoLayoutService {
27 27
28 /** 28 /**
29 + * Returns the top-level root layout, which always exists and cannot
30 + * be removed or associated directly with a region.
31 + *
32 + * @return root topology layout
33 + */
34 + UiTopoLayout getRootLayout();
35 +
36 + /**
29 * Returns the set of available layouts. 37 * Returns the set of available layouts.
30 * 38 *
31 * @return set of available layouts 39 * @return set of available layouts
...@@ -40,15 +48,23 @@ public interface UiTopoLayoutService { ...@@ -40,15 +48,23 @@ public interface UiTopoLayoutService {
40 */ 48 */
41 boolean addLayout(UiTopoLayout layout); 49 boolean addLayout(UiTopoLayout layout);
42 50
43 -
44 /** 51 /**
45 * Returns the layout with the specified identifier. 52 * Returns the layout with the specified identifier.
53 + *
46 * @param layoutId layout identifier 54 * @param layoutId layout identifier
47 * @return layout or null if no such layout is found 55 * @return layout or null if no such layout is found
48 */ 56 */
49 UiTopoLayout getLayout(UiTopoLayoutId layoutId); 57 UiTopoLayout getLayout(UiTopoLayoutId layoutId);
50 58
51 /** 59 /**
60 + * Returns the set of the child layouts of the specified layout.
61 + *
62 + * @param layoutId layout identifier
63 + * @return set of child layouts; empty set if layout has no children
64 + */
65 + Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId);
66 +
67 + /**
52 * Removes a layout from the system. 68 * Removes a layout from the system.
53 * 69 *
54 * @param layout the layout to remove 70 * @param layout the layout to remove
......
...@@ -26,16 +26,19 @@ public class UiTopoLayout { ...@@ -26,16 +26,19 @@ public class UiTopoLayout {
26 26
27 private final UiTopoLayoutId id; 27 private final UiTopoLayoutId id;
28 private final Region region; 28 private final Region region;
29 + private final UiTopoLayoutId parent;
29 30
30 /** 31 /**
31 * Created a new UI topology layout. 32 * Created a new UI topology layout.
32 * 33 *
33 * @param id layout identifier 34 * @param id layout identifier
34 * @param region backing region 35 * @param region backing region
36 + * @param parent identifier of the parent layout
35 */ 37 */
36 - public UiTopoLayout(UiTopoLayoutId id, Region region) { 38 + public UiTopoLayout(UiTopoLayoutId id, Region region, UiTopoLayoutId parent) {
37 this.id = id; 39 this.id = id;
38 this.region = region; 40 this.region = region;
41 + this.parent = parent;
39 } 42 }
40 43
41 /** 44 /**
...@@ -56,5 +59,14 @@ public class UiTopoLayout { ...@@ -56,5 +59,14 @@ public class UiTopoLayout {
56 return region; 59 return region;
57 } 60 }
58 61
62 + /**
63 + * Returns the parent layout identifier.
64 + *
65 + * @return parent layout identifier
66 + */
67 + public UiTopoLayoutId parent() {
68 + return parent;
69 + }
70 +
59 // TODO: additional properties pertinent to the layout 71 // TODO: additional properties pertinent to the layout
60 } 72 }
......
...@@ -27,7 +27,11 @@ import org.onosproject.ui.UiConnection; ...@@ -27,7 +27,11 @@ import org.onosproject.ui.UiConnection;
27 import org.onosproject.ui.UiExtensionService; 27 import org.onosproject.ui.UiExtensionService;
28 import org.onosproject.ui.UiMessageHandler; 28 import org.onosproject.ui.UiMessageHandler;
29 import org.onosproject.ui.UiMessageHandlerFactory; 29 import org.onosproject.ui.UiMessageHandlerFactory;
30 +import org.onosproject.ui.UiTopoLayoutService;
30 import org.onosproject.ui.UiTopoOverlayFactory; 31 import org.onosproject.ui.UiTopoOverlayFactory;
32 +import org.onosproject.ui.impl.topo.UiTopoSession;
33 +import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
34 +import org.onosproject.ui.model.topo.UiTopoLayout;
31 import org.onosproject.ui.topo.TopoConstants; 35 import org.onosproject.ui.topo.TopoConstants;
32 import org.slf4j.Logger; 36 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
...@@ -55,6 +59,8 @@ public class UiWebSocket ...@@ -55,6 +59,8 @@ public class UiWebSocket
55 private static final String USER = "user"; 59 private static final String USER = "user";
56 private static final String BOOTSTRAP = "bootstrap"; 60 private static final String BOOTSTRAP = "bootstrap";
57 61
62 + public static final String TOPO = "topo";
63 +
58 private static final long MAX_AGE_MS = 30_000; 64 private static final long MAX_AGE_MS = 30_000;
59 65
60 private static final byte PING = 0x9; 66 private static final byte PING = 0x9;
...@@ -63,11 +69,12 @@ public class UiWebSocket ...@@ -63,11 +69,12 @@ public class UiWebSocket
63 69
64 private final ObjectMapper mapper = new ObjectMapper(); 70 private final ObjectMapper mapper = new ObjectMapper();
65 private final ServiceDirectory directory; 71 private final ServiceDirectory directory;
66 -// private final UiTopoSession topoSession; 72 + private final UiTopoSession topoSession;
67 73
68 private Connection connection; 74 private Connection connection;
69 private FrameConnection control; 75 private FrameConnection control;
70 private String userName; 76 private String userName;
77 + private String currentView;
71 78
72 private long lastActive = System.currentTimeMillis(); 79 private long lastActive = System.currentTimeMillis();
73 80
...@@ -83,8 +90,9 @@ public class UiWebSocket ...@@ -83,8 +90,9 @@ public class UiWebSocket
83 public UiWebSocket(ServiceDirectory directory, String userName) { 90 public UiWebSocket(ServiceDirectory directory, String userName) {
84 this.directory = directory; 91 this.directory = directory;
85 this.userName = userName; 92 this.userName = userName;
86 -// this.topoSession = 93 + this.topoSession =
87 -// new UiTopoSession(this, directory.get(UiSharedTopologyModel.class)); 94 + new UiTopoSession(this, directory.get(UiSharedTopologyModel.class),
95 + directory.get(UiTopoLayoutService.class));
88 } 96 }
89 97
90 @Override 98 @Override
...@@ -92,6 +100,27 @@ public class UiWebSocket ...@@ -92,6 +100,27 @@ public class UiWebSocket
92 return userName; 100 return userName;
93 } 101 }
94 102
103 + @Override
104 + public UiTopoLayout currentLayout() {
105 + return topoSession.currentLayout();
106 + }
107 +
108 + @Override
109 + public void setCurrentLayout(UiTopoLayout topoLayout) {
110 + topoSession.setCurrentLayout(topoLayout);
111 + }
112 +
113 + @Override
114 + public String currentView() {
115 + return currentView;
116 + }
117 +
118 + @Override
119 + public void setCurrentView(String viewId) {
120 + currentView = viewId;
121 + topoSession.enableEvent(viewId.equals(TOPO));
122 + }
123 +
95 /** 124 /**
96 * Issues a close on the connection. 125 * Issues a close on the connection.
97 */ 126 */
...@@ -128,7 +157,7 @@ public class UiWebSocket ...@@ -128,7 +157,7 @@ public class UiWebSocket
128 this.connection = connection; 157 this.connection = connection;
129 this.control = (FrameConnection) connection; 158 this.control = (FrameConnection) connection;
130 try { 159 try {
131 -// topoSession.init(); 160 + topoSession.init();
132 createHandlersAndOverlays(); 161 createHandlersAndOverlays();
133 sendBootstrapData(); 162 sendBootstrapData();
134 log.info("GUI client connected -- user <{}>", userName); 163 log.info("GUI client connected -- user <{}>", userName);
...@@ -143,10 +172,10 @@ public class UiWebSocket ...@@ -143,10 +172,10 @@ public class UiWebSocket
143 172
144 @Override 173 @Override
145 public synchronized void onClose(int closeCode, String message) { 174 public synchronized void onClose(int closeCode, String message) {
146 -// topoSession.destroy(); 175 + topoSession.destroy();
147 destroyHandlersAndOverlays(); 176 destroyHandlersAndOverlays();
148 log.info("GUI client disconnected [close-code={}, message={}]", 177 log.info("GUI client disconnected [close-code={}, message={}]",
149 - closeCode, message); 178 + closeCode, message);
150 } 179 }
151 180
152 @Override 181 @Override
...@@ -228,7 +257,7 @@ public class UiWebSocket ...@@ -228,7 +257,7 @@ public class UiWebSocket
228 } 257 }
229 }); 258 });
230 log.debug("#handlers = {}, #overlays = {}", handlers.size(), 259 log.debug("#handlers = {}, #overlays = {}", handlers.size(),
231 - overlayCache.size()); 260 + overlayCache.size());
232 } 261 }
233 262
234 // Destroys message handlers. 263 // Destroys message handlers.
...@@ -255,7 +284,7 @@ public class UiWebSocket ...@@ -255,7 +284,7 @@ public class UiWebSocket
255 .put(ID, node.id().toString()) 284 .put(ID, node.id().toString())
256 .put(IP, node.ip().toString()) 285 .put(IP, node.ip().toString())
257 .put(TopoConstants.Glyphs.UI_ATTACHED, 286 .put(TopoConstants.Glyphs.UI_ATTACHED,
258 - node.equals(service.getLocalNode())); 287 + node.equals(service.getLocalNode()));
259 instances.add(instance); 288 instances.add(instance);
260 } 289 }
261 290
......
...@@ -35,7 +35,11 @@ import org.slf4j.Logger; ...@@ -35,7 +35,11 @@ import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory; 35 import org.slf4j.LoggerFactory;
36 36
37 import java.util.Map; 37 import java.util.Map;
38 +import java.util.Objects;
38 import java.util.Set; 39 import java.util.Set;
40 +import java.util.stream.Collectors;
41 +
42 +import static com.google.common.base.Preconditions.checkNotNull;
39 43
40 /** 44 /**
41 * Manages the user interface topology layouts. 45 * Manages the user interface topology layouts.
...@@ -47,6 +51,11 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { ...@@ -47,6 +51,11 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
47 51
48 private final Logger log = LoggerFactory.getLogger(getClass()); 52 private final Logger log = LoggerFactory.getLogger(getClass());
49 53
54 + private static final String ID_NULL = "Layout ID cannot be null";
55 + private static final String LAYOUT_NULL = "Layout cannot be null";
56 +
57 + private static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
58 +
50 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected StorageService storageService; 60 protected StorageService storageService;
52 61
...@@ -57,6 +66,7 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { ...@@ -57,6 +66,7 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
57 public void activate() { 66 public void activate() {
58 KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder() 67 KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
59 .register(KryoNamespaces.API) 68 .register(KryoNamespaces.API)
69 + .register(UiTopoLayoutId.class)
60 .register(UiTopoLayout.class); 70 .register(UiTopoLayout.class);
61 71
62 layouts = storageService.<UiTopoLayoutId, UiTopoLayout>consistentMapBuilder() 72 layouts = storageService.<UiTopoLayoutId, UiTopoLayout>consistentMapBuilder()
...@@ -66,6 +76,9 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { ...@@ -66,6 +76,9 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
66 .build(); 76 .build();
67 layoutMap = layouts.asJavaMap(); 77 layoutMap = layouts.asJavaMap();
68 78
79 + // Create and add the default layout, if needed.
80 + layoutMap.computeIfAbsent(DEFAULT_ID, k -> new UiTopoLayout(k, null, null));
81 +
69 log.info("Started"); 82 log.info("Started");
70 } 83 }
71 84
...@@ -76,22 +89,38 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { ...@@ -76,22 +89,38 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
76 89
77 90
78 @Override 91 @Override
92 + public UiTopoLayout getRootLayout() {
93 + return getLayout(DEFAULT_ID);
94 + }
95 +
96 + @Override
79 public Set<UiTopoLayout> getLayouts() { 97 public Set<UiTopoLayout> getLayouts() {
80 return ImmutableSet.copyOf(layoutMap.values()); 98 return ImmutableSet.copyOf(layoutMap.values());
81 } 99 }
82 100
83 @Override 101 @Override
84 public boolean addLayout(UiTopoLayout layout) { 102 public boolean addLayout(UiTopoLayout layout) {
103 + checkNotNull(layout, LAYOUT_NULL);
85 return layouts.put(layout.id(), layout) == null; 104 return layouts.put(layout.id(), layout) == null;
86 } 105 }
87 106
88 @Override 107 @Override
89 public UiTopoLayout getLayout(UiTopoLayoutId layoutId) { 108 public UiTopoLayout getLayout(UiTopoLayoutId layoutId) {
109 + checkNotNull(layoutId, ID_NULL);
90 return layoutMap.get(layoutId); 110 return layoutMap.get(layoutId);
91 } 111 }
92 112
93 @Override 113 @Override
114 + public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
115 + checkNotNull(layoutId, ID_NULL);
116 + return layoutMap.values().stream()
117 + .filter(l -> Objects.equals(l.parent(), layoutId))
118 + .collect(Collectors.toSet());
119 + }
120 +
121 + @Override
94 public boolean removeLayout(UiTopoLayout layout) { 122 public boolean removeLayout(UiTopoLayout layout) {
123 + checkNotNull(layout, LAYOUT_NULL);
95 return layouts.remove(layout.id()) != null; 124 return layouts.remove(layout.id()) != null;
96 } 125 }
97 126
......
...@@ -45,19 +45,24 @@ public class UiTopoSession implements UiModelListener { ...@@ -45,19 +45,24 @@ public class UiTopoSession implements UiModelListener {
45 45
46 private boolean registered = false; 46 private boolean registered = false;
47 47
48 - private UiTopoLayoutService service; 48 + private UiTopoLayoutService layoutService;
49 private UiTopoLayout currentLayout; 49 private UiTopoLayout currentLayout;
50 + private boolean messagesEnabled;
50 51
51 /** 52 /**
52 * Creates a new topology session for the specified web socket connection. 53 * Creates a new topology session for the specified web socket connection.
53 * 54 *
54 - * @param webSocket web socket 55 + * @param webSocket web socket
55 - * @param model share topology model 56 + * @param model share topology model
57 + * @param layoutService topology layout service
56 */ 58 */
57 - public UiTopoSession(UiWebSocket webSocket, UiSharedTopologyModel model) { 59 + public UiTopoSession(UiWebSocket webSocket,
60 + UiSharedTopologyModel model,
61 + UiTopoLayoutService layoutService) {
58 this.webSocket = webSocket; 62 this.webSocket = webSocket;
59 this.username = webSocket.userName(); 63 this.username = webSocket.userName();
60 this.sharedModel = model; 64 this.sharedModel = model;
65 + this.layoutService = layoutService;
61 } 66 }
62 67
63 /** 68 /**
...@@ -67,6 +72,7 @@ public class UiTopoSession implements UiModelListener { ...@@ -67,6 +72,7 @@ public class UiTopoSession implements UiModelListener {
67 if (!registered) { 72 if (!registered) {
68 log.debug("{} : Registering with shared model", this); 73 log.debug("{} : Registering with shared model", this);
69 sharedModel.register(this); 74 sharedModel.register(this);
75 + currentLayout = layoutService.getRootLayout();
70 registered = true; 76 registered = true;
71 } else { 77 } else {
72 log.warn("already registered"); 78 log.warn("already registered");
...@@ -96,4 +102,31 @@ public class UiTopoSession implements UiModelListener { ...@@ -96,4 +102,31 @@ public class UiTopoSession implements UiModelListener {
96 log.info("Event received: {}", event); 102 log.info("Event received: {}", event);
97 // TODO: handle model events from the cache... 103 // TODO: handle model events from the cache...
98 } 104 }
105 +
106 + /**
107 + * Returns the current layout context.
108 + *
109 + * @return current topology layout
110 + */
111 + public UiTopoLayout currentLayout() {
112 + return currentLayout;
113 + }
114 +
115 + /**
116 + * Changes the current layout context to the specified layout.
117 + *
118 + * @param topoLayout new topology layout context
119 + */
120 + public void setCurrentLayout(UiTopoLayout topoLayout) {
121 + currentLayout = topoLayout;
122 + }
123 +
124 + /**
125 + * Enables or disables the transmission of topology event update messages.
126 + *
127 + * @param enabled true if messages should be sent
128 + */
129 + public void enableEvent(boolean enabled) {
130 + messagesEnabled = enabled;
131 + }
99 } 132 }
......
...@@ -224,7 +224,10 @@ class ModelCache { ...@@ -224,7 +224,10 @@ class ModelCache {
224 } 224 }
225 225
226 private void updateDevice(UiDevice device) { 226 private void updateDevice(UiDevice device) {
227 - device.setRegionId(services.region().getRegionForDevice(device.id()).id()); 227 + Region regionForDevice = services.region().getRegionForDevice(device.id());
228 + if (regionForDevice != null) {
229 + device.setRegionId(regionForDevice.id());
230 + }
228 } 231 }
229 232
230 private void loadDevices() { 233 private void loadDevices() {
......
...@@ -66,7 +66,7 @@ import org.slf4j.LoggerFactory; ...@@ -66,7 +66,7 @@ import org.slf4j.LoggerFactory;
66 /** 66 /**
67 * Service that creates and maintains the UI-model of the network topology. 67 * Service that creates and maintains the UI-model of the network topology.
68 */ 68 */
69 -@Component(immediate = true, enabled = false) 69 +@Component(immediate = true, enabled = true)
70 @Service(value = UiSharedTopologyModel.class) 70 @Service(value = UiSharedTopologyModel.class)
71 public final class UiSharedTopologyModel 71 public final class UiSharedTopologyModel
72 extends AbstractListenerManager<UiModelEvent, UiModelListener> { 72 extends AbstractListenerManager<UiModelEvent, UiModelListener> {
......
...@@ -40,11 +40,11 @@ public class UiTopoLayoutManagerTest { ...@@ -40,11 +40,11 @@ public class UiTopoLayoutManagerTest {
40 private static final UiTopoLayout L1 = 40 private static final UiTopoLayout L1 =
41 new UiTopoLayout(UiTopoLayoutId.layoutId("l1"), 41 new UiTopoLayout(UiTopoLayoutId.layoutId("l1"),
42 new DefaultRegion(RegionId.regionId("r1"), "R1", 42 new DefaultRegion(RegionId.regionId("r1"), "R1",
43 - Region.Type.CAMPUS, null)); 43 + Region.Type.CAMPUS, null), null);
44 private static final UiTopoLayout L2 = 44 private static final UiTopoLayout L2 =
45 new UiTopoLayout(UiTopoLayoutId.layoutId("l2"), 45 new UiTopoLayout(UiTopoLayoutId.layoutId("l2"),
46 new DefaultRegion(RegionId.regionId("r2"), "R2", 46 new DefaultRegion(RegionId.regionId("r2"), "R2",
47 - Region.Type.CAMPUS, null)); 47 + Region.Type.CAMPUS, null), null);
48 48
49 @Before 49 @Before
50 public void setUp() { 50 public void setUp() {
...@@ -62,14 +62,14 @@ public class UiTopoLayoutManagerTest { ...@@ -62,14 +62,14 @@ public class UiTopoLayoutManagerTest {
62 62
63 @Test 63 @Test
64 public void basics() { 64 public void basics() {
65 - assertTrue("should be no layout", svc.getLayouts().isEmpty()); 65 + assertEquals("should be just default layout", 1, svc.getLayouts().size());
66 svc.addLayout(L1); 66 svc.addLayout(L1);
67 svc.addLayout(L2); 67 svc.addLayout(L2);
68 - assertEquals("incorrect number of layouts", 2, svc.getLayouts().size()); 68 + assertEquals("incorrect number of layouts", 3, svc.getLayouts().size());
69 assertEquals("incorrect layout", L1.id(), svc.getLayout(L1.id()).id()); 69 assertEquals("incorrect layout", L1.id(), svc.getLayout(L1.id()).id());
70 assertEquals("incorrect layout", L2.id(), svc.getLayout(L2.id()).id()); 70 assertEquals("incorrect layout", L2.id(), svc.getLayout(L2.id()).id());
71 svc.removeLayout(L1); 71 svc.removeLayout(L1);
72 - assertEquals("incorrect number of layouts", 1, svc.getLayouts().size()); 72 + assertEquals("incorrect number of layouts", 2, svc.getLayouts().size());
73 assertNull("layout should be gone", svc.getLayout(L1.id())); 73 assertNull("layout should be gone", svc.getLayout(L1.id()));
74 assertEquals("incorrect layout", L2.id(), svc.getLayout(L2.id()).id()); 74 assertEquals("incorrect layout", L2.id(), svc.getLayout(L2.id()).id());
75 } 75 }
......