Committed by
Gerrit Code Review
ONOS-1479 - GUI Topology Overlay Work - (WIP)
- UiExtension now uses Builder Pattern; added topology overlay factory. - Refactored UiExtensionTest (and other classes) to use builder. - Created UiTopoOverlayFactory, UiTopoOverlay, and TopoOverlayCache. - Started implementation of TrafficOverlay. - Inject TopoOverlayCache into TopologyViewMessageHandler; added TopoSelectOverlay request handler. - Modified UiExtensionManager to create traffic overlay. - Augmented UiWebSocket to create overlays on demand, and inject overlay cache into topo view message handler. - added client side wiring to switch overlays. Change-Id: I6f99596aefb3b87382517ce929d268a2447545ee
Showing
14 changed files
with
545 additions
and
83 deletions
| ... | @@ -62,7 +62,9 @@ public class IntentPerfUi { | ... | @@ -62,7 +62,9 @@ public class IntentPerfUi { |
| 62 | ); | 62 | ); |
| 63 | 63 | ||
| 64 | private UiExtension uiExtension = | 64 | private UiExtension uiExtension = |
| 65 | - new UiExtension(views, this::newHandlers, getClass().getClassLoader()); | 65 | + new UiExtension.Builder(getClass().getClassLoader(), views) |
| 66 | + .messageHandlerFactory(this::newHandlers) | ||
| 67 | + .build(); | ||
| 66 | 68 | ||
| 67 | private IntentPerfCollector collector; | 69 | private IntentPerfCollector collector; |
| 68 | 70 | ... | ... |
| ... | @@ -15,61 +15,47 @@ | ... | @@ -15,61 +15,47 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.ui; | 16 | package org.onosproject.ui; |
| 17 | 17 | ||
| 18 | -import com.google.common.collect.ImmutableList; | ||
| 19 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
| 20 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
| 21 | 20 | ||
| 22 | import java.io.InputStream; | 21 | import java.io.InputStream; |
| 22 | +import java.util.ArrayList; | ||
| 23 | import java.util.List; | 23 | import java.util.List; |
| 24 | 24 | ||
| 25 | +import static com.google.common.base.Preconditions.checkArgument; | ||
| 25 | import static com.google.common.base.Preconditions.checkNotNull; | 26 | import static com.google.common.base.Preconditions.checkNotNull; |
| 26 | 27 | ||
| 27 | /** | 28 | /** |
| 28 | * User interface extension. | 29 | * User interface extension. |
| 29 | */ | 30 | */ |
| 30 | -public class UiExtension { | 31 | +public final class UiExtension { |
| 31 | 32 | ||
| 32 | private final Logger log = LoggerFactory.getLogger(getClass()); | 33 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 33 | 34 | ||
| 34 | private static final String VIEW_PREFIX = "app/view/"; | 35 | private static final String VIEW_PREFIX = "app/view/"; |
| 36 | + private static final String EMPTY = ""; | ||
| 37 | + private static final String SLASH = "/"; | ||
| 38 | + private static final String CSS_HTML = "css.html"; | ||
| 39 | + private static final String JS_HTML = "js.html"; | ||
| 35 | 40 | ||
| 36 | - private final String prefix; | ||
| 37 | private final ClassLoader classLoader; | 41 | private final ClassLoader classLoader; |
| 42 | + private final String resourcePath; | ||
| 38 | private final List<UiView> views; | 43 | private final List<UiView> views; |
| 39 | private final UiMessageHandlerFactory messageHandlerFactory; | 44 | private final UiMessageHandlerFactory messageHandlerFactory; |
| 40 | - | 45 | + private final UiTopoOverlayFactory topoOverlayFactory; |
| 41 | - /** | 46 | + |
| 42 | - * Creates a user interface extension for loading CSS and JS injections | 47 | + |
| 43 | - * from {@code css.html} and {@code js.html} resources, respectively. | 48 | + // private constructor - only the builder calls this |
| 44 | - * | 49 | + private UiExtension(ClassLoader cl, String path, List<UiView> views, |
| 45 | - * @param views list of contributed views | 50 | + UiMessageHandlerFactory mhFactory, |
| 46 | - * @param messageHandlerFactory optional message handler factory | 51 | + UiTopoOverlayFactory toFactory) { |
| 47 | - * @param classLoader class-loader for user interface resources | 52 | + this.classLoader = cl; |
| 48 | - */ | 53 | + this.resourcePath = path; |
| 49 | - public UiExtension(List<UiView> views, | 54 | + this.views = views; |
| 50 | - UiMessageHandlerFactory messageHandlerFactory, | 55 | + this.messageHandlerFactory = mhFactory; |
| 51 | - ClassLoader classLoader) { | 56 | + this.topoOverlayFactory = toFactory; |
| 52 | - this(views, messageHandlerFactory, null, classLoader); | ||
| 53 | } | 57 | } |
| 54 | 58 | ||
| 55 | - /** | ||
| 56 | - * Creates a user interface extension using custom resource prefix. It | ||
| 57 | - * loads CSS and JS injections from {@code path/css.html} and | ||
| 58 | - * {@code prefix/js.html} resources, respectively. | ||
| 59 | - * | ||
| 60 | - * @param views list of user interface views | ||
| 61 | - * @param messageHandlerFactory optional message handler factory | ||
| 62 | - * @param path resource path prefix | ||
| 63 | - * @param classLoader class-loader for user interface resources | ||
| 64 | - */ | ||
| 65 | - public UiExtension(List<UiView> views, | ||
| 66 | - UiMessageHandlerFactory messageHandlerFactory, | ||
| 67 | - String path, ClassLoader classLoader) { | ||
| 68 | - this.views = checkNotNull(ImmutableList.copyOf(views), "Views cannot be null"); | ||
| 69 | - this.messageHandlerFactory = messageHandlerFactory; | ||
| 70 | - this.prefix = path != null ? (path + "/") : ""; | ||
| 71 | - this.classLoader = checkNotNull(classLoader, "Class loader must be specified"); | ||
| 72 | - } | ||
| 73 | 59 | ||
| 74 | /** | 60 | /** |
| 75 | * Returns input stream containing CSS inclusion statements. | 61 | * Returns input stream containing CSS inclusion statements. |
| ... | @@ -77,7 +63,7 @@ public class UiExtension { | ... | @@ -77,7 +63,7 @@ public class UiExtension { |
| 77 | * @return CSS inclusion statements | 63 | * @return CSS inclusion statements |
| 78 | */ | 64 | */ |
| 79 | public InputStream css() { | 65 | public InputStream css() { |
| 80 | - return getStream(prefix + "css.html"); | 66 | + return getStream(resourcePath + CSS_HTML); |
| 81 | } | 67 | } |
| 82 | 68 | ||
| 83 | /** | 69 | /** |
| ... | @@ -86,7 +72,7 @@ public class UiExtension { | ... | @@ -86,7 +72,7 @@ public class UiExtension { |
| 86 | * @return JavaScript inclusion statements | 72 | * @return JavaScript inclusion statements |
| 87 | */ | 73 | */ |
| 88 | public InputStream js() { | 74 | public InputStream js() { |
| 89 | - return getStream(prefix + "js.html"); | 75 | + return getStream(resourcePath + JS_HTML); |
| 90 | } | 76 | } |
| 91 | 77 | ||
| 92 | /** | 78 | /** |
| ... | @@ -106,18 +92,28 @@ public class UiExtension { | ... | @@ -106,18 +92,28 @@ public class UiExtension { |
| 106 | * @return resource input stream | 92 | * @return resource input stream |
| 107 | */ | 93 | */ |
| 108 | public InputStream resource(String viewId, String path) { | 94 | public InputStream resource(String viewId, String path) { |
| 109 | - return getStream(VIEW_PREFIX + viewId + "/" + path); | 95 | + return getStream(VIEW_PREFIX + viewId + SLASH + path); |
| 110 | } | 96 | } |
| 111 | 97 | ||
| 112 | /** | 98 | /** |
| 113 | - * Returns message handler factory. | 99 | + * Returns message handler factory, if one was defined. |
| 114 | * | 100 | * |
| 115 | - * @return message handlers | 101 | + * @return message handler factory |
| 116 | */ | 102 | */ |
| 117 | public UiMessageHandlerFactory messageHandlerFactory() { | 103 | public UiMessageHandlerFactory messageHandlerFactory() { |
| 118 | return messageHandlerFactory; | 104 | return messageHandlerFactory; |
| 119 | } | 105 | } |
| 120 | 106 | ||
| 107 | + /** | ||
| 108 | + * Returns the topology overlay factory, if one was defined. | ||
| 109 | + * | ||
| 110 | + * @return topology overlay factory | ||
| 111 | + */ | ||
| 112 | + public UiTopoOverlayFactory topoOverlayFactory() { | ||
| 113 | + return topoOverlayFactory; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + | ||
| 121 | // Returns the resource input stream from the specified class-loader. | 117 | // Returns the resource input stream from the specified class-loader. |
| 122 | private InputStream getStream(String path) { | 118 | private InputStream getStream(String path) { |
| 123 | InputStream stream = classLoader.getResourceAsStream(path); | 119 | InputStream stream = classLoader.getResourceAsStream(path); |
| ... | @@ -128,4 +124,76 @@ public class UiExtension { | ... | @@ -128,4 +124,76 @@ public class UiExtension { |
| 128 | } | 124 | } |
| 129 | 125 | ||
| 130 | 126 | ||
| 127 | + /** | ||
| 128 | + * UI Extension Builder. | ||
| 129 | + */ | ||
| 130 | + public static class Builder { | ||
| 131 | + private ClassLoader classLoader; | ||
| 132 | + | ||
| 133 | + private String resourcePath = EMPTY; | ||
| 134 | + private List<UiView> views = new ArrayList<>(); | ||
| 135 | + private UiMessageHandlerFactory messageHandlerFactory = null; | ||
| 136 | + private UiTopoOverlayFactory topoOverlayFactory = null; | ||
| 137 | + | ||
| 138 | + /** | ||
| 139 | + * Create a builder with the given class loader. | ||
| 140 | + * Resource path defaults to "". | ||
| 141 | + * Views defaults to an empty list. | ||
| 142 | + * Both Message and TopoOverlay factories default to null. | ||
| 143 | + * | ||
| 144 | + * @param cl the classloader | ||
| 145 | + */ | ||
| 146 | + public Builder(ClassLoader cl, List<UiView> views) { | ||
| 147 | + checkNotNull(cl, "Must provide a class loader"); | ||
| 148 | + checkArgument(views.size() > 0, "Must provide at least one view"); | ||
| 149 | + this.classLoader = cl; | ||
| 150 | + this.views = views; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + /** | ||
| 154 | + * Set the resource path. That is, path to where the CSS and JS | ||
| 155 | + * files are located. This value should | ||
| 156 | + * | ||
| 157 | + * @param path resource path | ||
| 158 | + * @return self, for chaining | ||
| 159 | + */ | ||
| 160 | + public Builder resourcePath(String path) { | ||
| 161 | + this.resourcePath = path == null ? EMPTY : path + SLASH; | ||
| 162 | + return this; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + /** | ||
| 166 | + * Sets the message handler factory for this extension. | ||
| 167 | + * | ||
| 168 | + * @param mhFactory message handler factory | ||
| 169 | + * @return self, for chaining | ||
| 170 | + */ | ||
| 171 | + public Builder messageHandlerFactory(UiMessageHandlerFactory mhFactory) { | ||
| 172 | + this.messageHandlerFactory = mhFactory; | ||
| 173 | + return this; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + /** | ||
| 177 | + * Sets the topology overlay factory for this extension. | ||
| 178 | + * | ||
| 179 | + * @param toFactory topology overlay factory | ||
| 180 | + * @return self, for chaining | ||
| 181 | + */ | ||
| 182 | + public Builder topoOverlayFactory(UiTopoOverlayFactory toFactory) { | ||
| 183 | + this.topoOverlayFactory = toFactory; | ||
| 184 | + return this; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + /** | ||
| 188 | + * Builds the UI extension. | ||
| 189 | + * | ||
| 190 | + * @return UI extension instance | ||
| 191 | + */ | ||
| 192 | + public UiExtension build() { | ||
| 193 | + return new UiExtension(classLoader, resourcePath, views, | ||
| 194 | + messageHandlerFactory, topoOverlayFactory); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + } | ||
| 198 | + | ||
| 131 | } | 199 | } | ... | ... |
| ... | @@ -107,8 +107,9 @@ public abstract class UiMessageHandler { | ... | @@ -107,8 +107,9 @@ public abstract class UiMessageHandler { |
| 107 | void exec(String eventType, long sid, ObjectNode payload) { | 107 | void exec(String eventType, long sid, ObjectNode payload) { |
| 108 | RequestHandler requestHandler = handlerMap.get(eventType); | 108 | RequestHandler requestHandler = handlerMap.get(eventType); |
| 109 | if (requestHandler != null) { | 109 | if (requestHandler != null) { |
| 110 | - log.debug("process {} event...", eventType); | ||
| 111 | requestHandler.process(sid, payload); | 110 | requestHandler.process(sid, payload); |
| 111 | + } else { | ||
| 112 | + log.warn("no request handler for event type {}", eventType); | ||
| 112 | } | 113 | } |
| 113 | } | 114 | } |
| 114 | 115 | ... | ... |
| 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; | ||
| 19 | + | ||
| 20 | +import org.slf4j.Logger; | ||
| 21 | +import org.slf4j.LoggerFactory; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Represents user interface topology view overlay. | ||
| 25 | + */ | ||
| 26 | +public class UiTopoOverlay { | ||
| 27 | + | ||
| 28 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 29 | + | ||
| 30 | + private final String id; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Creates a new user interface topology view overlay descriptor. | ||
| 34 | + * | ||
| 35 | + * @param id overlay identifier | ||
| 36 | + */ | ||
| 37 | + public UiTopoOverlay(String id) { | ||
| 38 | + this.id = id; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * Returns the identifier for this overlay. | ||
| 43 | + * | ||
| 44 | + * @return the identifier | ||
| 45 | + */ | ||
| 46 | + public String id() { | ||
| 47 | + return id; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Callback invoked to initialize this overlay, soon after creation. | ||
| 52 | + * This default implementation does nothing. | ||
| 53 | + */ | ||
| 54 | + public void init() { | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * Callback invoked when this overlay is activated. | ||
| 59 | + */ | ||
| 60 | + public void activate() { | ||
| 61 | + log.debug("Overlay '{}' Activated", id); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * Callback invoked when this overlay is deactivated. | ||
| 66 | + */ | ||
| 67 | + public void deactivate() { | ||
| 68 | + log.debug("Overlay '{}' Deactivated", id); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Callback invoked to destroy this instance by cleaning up any | ||
| 73 | + * internal state ready for garbage collection. | ||
| 74 | + * This default implementation does nothing. | ||
| 75 | + */ | ||
| 76 | + public void destroy() { | ||
| 77 | + } | ||
| 78 | +} |
| 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; | ||
| 19 | + | ||
| 20 | +import java.util.Collection; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Abstraction of an entity capable of producing one or more topology | ||
| 24 | + * overlay handlers specific to a given user interface connection. | ||
| 25 | + */ | ||
| 26 | +public interface UiTopoOverlayFactory { | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * Produces a collection of new overlay handlers. | ||
| 30 | + * | ||
| 31 | + * @return collection of new overlay handlers | ||
| 32 | + */ | ||
| 33 | + Collection<UiTopoOverlay> newOverlays(); | ||
| 34 | +} |
| ... | @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; | ... | @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; |
| 19 | import org.junit.Test; | 19 | import org.junit.Test; |
| 20 | 20 | ||
| 21 | import java.io.IOException; | 21 | import java.io.IOException; |
| 22 | +import java.util.List; | ||
| 22 | 23 | ||
| 23 | import static com.google.common.io.ByteStreams.toByteArray; | 24 | import static com.google.common.io.ByteStreams.toByteArray; |
| 24 | import static org.junit.Assert.*; | 25 | import static org.junit.Assert.*; |
| ... | @@ -29,29 +30,111 @@ import static org.onosproject.ui.UiView.Category.OTHER; | ... | @@ -29,29 +30,111 @@ import static org.onosproject.ui.UiView.Category.OTHER; |
| 29 | */ | 30 | */ |
| 30 | public class UiExtensionTest { | 31 | public class UiExtensionTest { |
| 31 | 32 | ||
| 33 | + private static final String FOO_ID = "foo"; | ||
| 34 | + private static final String FOO_LABEL = "Foo View"; | ||
| 35 | + private static final String BAR_ID = "bar"; | ||
| 36 | + private static final String BAR_LABEL = "Bar View"; | ||
| 37 | + private static final String CUSTOM = "custom"; | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + private static final UiView FOO_VIEW = new UiView(OTHER, FOO_ID, FOO_LABEL); | ||
| 41 | + private static final UiView BAR_VIEW = new UiView(OTHER, BAR_ID, BAR_LABEL); | ||
| 42 | + private static final UiView HIDDEN_VIEW = new UiViewHidden(FOO_ID); | ||
| 43 | + | ||
| 44 | + private static final UiMessageHandlerFactory MH_FACTORY = () -> null; | ||
| 45 | + private static final UiTopoOverlayFactory TO_FACTORY = () -> null; | ||
| 46 | + | ||
| 47 | + private final ClassLoader cl = getClass().getClassLoader(); | ||
| 48 | + | ||
| 49 | + private List<UiView> viewList; | ||
| 50 | + private UiExtension ext; | ||
| 51 | + private String css; | ||
| 52 | + private String js; | ||
| 53 | + private UiView view; | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + | ||
| 32 | @Test | 57 | @Test |
| 33 | public void basics() throws IOException { | 58 | public void basics() throws IOException { |
| 34 | - UiExtension ext = new UiExtension(ImmutableList.of(new UiView(OTHER, "foo", "Foo View")), | 59 | + viewList = ImmutableList.of(FOO_VIEW); |
| 35 | - null, | 60 | + ext = new UiExtension.Builder(cl, viewList).build(); |
| 36 | - getClass().getClassLoader()); | 61 | + |
| 37 | - String css = new String(toByteArray(ext.css())); | 62 | + css = new String(toByteArray(ext.css())); |
| 38 | assertTrue("incorrect css stream", css.contains("foo-css")); | 63 | assertTrue("incorrect css stream", css.contains("foo-css")); |
| 39 | - String js = new String(toByteArray(ext.js())); | 64 | + js = new String(toByteArray(ext.js())); |
| 40 | assertTrue("incorrect js stream", js.contains("foo-js")); | 65 | assertTrue("incorrect js stream", js.contains("foo-js")); |
| 41 | - assertEquals("incorrect view id", "foo", ext.views().get(0).id()); | 66 | + |
| 42 | - assertEquals("incorrect view category", OTHER, ext.views().get(0).category()); | 67 | + assertEquals("expected 1 view", 1, ext.views().size()); |
| 43 | - assertNull("incorrect handler factory", ext.messageHandlerFactory()); | 68 | + view = ext.views().get(0); |
| 69 | + assertEquals("wrong view category", OTHER, view.category()); | ||
| 70 | + assertEquals("wrong view id", FOO_ID, view.id()); | ||
| 71 | + assertEquals("wrong view label", FOO_LABEL, view.label()); | ||
| 72 | + | ||
| 73 | + assertNull("unexpected message handler factory", ext.messageHandlerFactory()); | ||
| 74 | + assertNull("unexpected topo overlay factory", ext.topoOverlayFactory()); | ||
| 44 | } | 75 | } |
| 45 | 76 | ||
| 46 | @Test | 77 | @Test |
| 47 | public void withPath() throws IOException { | 78 | public void withPath() throws IOException { |
| 48 | - UiExtension ext = new UiExtension(ImmutableList.of(new UiView(OTHER, "foo", "Foo View")), | 79 | + viewList = ImmutableList.of(FOO_VIEW); |
| 49 | - null, "custom", getClass().getClassLoader()); | 80 | + ext = new UiExtension.Builder(cl, viewList) |
| 50 | - String css = new String(toByteArray(ext.css())); | 81 | + .resourcePath(CUSTOM) |
| 82 | + .build(); | ||
| 83 | + | ||
| 84 | + css = new String(toByteArray(ext.css())); | ||
| 51 | assertTrue("incorrect css stream", css.contains("custom-css")); | 85 | assertTrue("incorrect css stream", css.contains("custom-css")); |
| 52 | - String js = new String(toByteArray(ext.js())); | 86 | + js = new String(toByteArray(ext.js())); |
| 53 | assertTrue("incorrect js stream", js.contains("custom-js")); | 87 | assertTrue("incorrect js stream", js.contains("custom-js")); |
| 54 | - assertEquals("incorrect view id", "foo", ext.views().get(0).id()); | 88 | + |
| 55 | - assertNull("incorrect handler factory", ext.messageHandlerFactory()); | 89 | + assertEquals("expected 1 view", 1, ext.views().size()); |
| 90 | + view = ext.views().get(0); | ||
| 91 | + assertEquals("wrong view category", OTHER, view.category()); | ||
| 92 | + assertEquals("wrong view id", FOO_ID, view.id()); | ||
| 93 | + assertEquals("wrong view label", FOO_LABEL, view.label()); | ||
| 94 | + | ||
| 95 | + assertNull("unexpected message handler factory", ext.messageHandlerFactory()); | ||
| 96 | + assertNull("unexpected topo overlay factory", ext.topoOverlayFactory()); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @Test | ||
| 100 | + public void messageHandlerFactory() { | ||
| 101 | + viewList = ImmutableList.of(FOO_VIEW); | ||
| 102 | + ext = new UiExtension.Builder(cl, viewList) | ||
| 103 | + .messageHandlerFactory(MH_FACTORY) | ||
| 104 | + .build(); | ||
| 105 | + | ||
| 106 | + assertEquals("wrong message handler factory", MH_FACTORY, | ||
| 107 | + ext.messageHandlerFactory()); | ||
| 108 | + assertNull("unexpected topo overlay factory", ext.topoOverlayFactory()); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + @Test | ||
| 112 | + public void topoOverlayFactory() { | ||
| 113 | + viewList = ImmutableList.of(HIDDEN_VIEW); | ||
| 114 | + ext = new UiExtension.Builder(cl, viewList) | ||
| 115 | + .topoOverlayFactory(TO_FACTORY) | ||
| 116 | + .build(); | ||
| 117 | + | ||
| 118 | + assertNull("unexpected message handler factory", ext.messageHandlerFactory()); | ||
| 119 | + assertEquals("wrong topo overlay factory", TO_FACTORY, | ||
| 120 | + ext.topoOverlayFactory()); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + @Test | ||
| 124 | + public void twoViews() { | ||
| 125 | + viewList = ImmutableList.of(FOO_VIEW, BAR_VIEW); | ||
| 126 | + ext = new UiExtension.Builder(cl, viewList).build(); | ||
| 127 | + | ||
| 128 | + assertEquals("expected 2 views", 2, ext.views().size()); | ||
| 129 | + | ||
| 130 | + view = ext.views().get(0); | ||
| 131 | + assertEquals("wrong view category", OTHER, view.category()); | ||
| 132 | + assertEquals("wrong view id", FOO_ID, view.id()); | ||
| 133 | + assertEquals("wrong view label", FOO_LABEL, view.label()); | ||
| 134 | + | ||
| 135 | + view = ext.views().get(1); | ||
| 136 | + assertEquals("wrong view category", OTHER, view.category()); | ||
| 137 | + assertEquals("wrong view id", BAR_ID, view.id()); | ||
| 138 | + assertEquals("wrong view label", BAR_LABEL, view.label()); | ||
| 56 | } | 139 | } |
| 57 | } | 140 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
tools/package/archetypes/ui/src/main/resources/archetype-resources/src/main/java/AppUiComponent.java
| ... | @@ -57,8 +57,9 @@ public class AppUiComponent { | ... | @@ -57,8 +57,9 @@ public class AppUiComponent { |
| 57 | 57 | ||
| 58 | // Application UI extension | 58 | // Application UI extension |
| 59 | protected UiExtension extension = | 59 | protected UiExtension extension = |
| 60 | - new UiExtension(uiViews, messageHandlerFactory, | 60 | + new UiExtension.Builder(getClass().getClassLoader(), uiViews) |
| 61 | - getClass().getClassLoader()); | 61 | + .messageHandlerFactory(messageHandlerFactory) |
| 62 | + .build(); | ||
| 62 | 63 | ||
| 63 | @Activate | 64 | @Activate |
| 64 | protected void activate() { | 65 | protected void activate() { | ... | ... |
| 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; | ||
| 19 | + | ||
| 20 | +import org.onosproject.ui.UiTopoOverlay; | ||
| 21 | + | ||
| 22 | +import java.util.HashMap; | ||
| 23 | +import java.util.Map; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * A cache of {@link org.onosproject.ui.UiTopoOverlay}'s that were registered | ||
| 27 | + * at the time the UI connection was established. | ||
| 28 | + */ | ||
| 29 | +public class TopoOverlayCache { | ||
| 30 | + | ||
| 31 | + private final Map<String, UiTopoOverlay> overlays = new HashMap<>(); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * Adds a topology overlay to the cache. | ||
| 35 | + * | ||
| 36 | + * @param overlay a topology overlay | ||
| 37 | + */ | ||
| 38 | + public void add(UiTopoOverlay overlay) { | ||
| 39 | + overlays.put(overlay.id(), overlay); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Invoked when the cache is no longer needed. | ||
| 44 | + */ | ||
| 45 | + public void destroy() { | ||
| 46 | + overlays.clear(); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * Switching currently selected overlay. | ||
| 51 | + * | ||
| 52 | + * @param deact identity of overlay to deactivate | ||
| 53 | + * @param act identity of overlay to activate | ||
| 54 | + */ | ||
| 55 | + public void switchOverlay(String deact, String act) { | ||
| 56 | + UiTopoOverlay toDeactivate = getOverlay(deact); | ||
| 57 | + UiTopoOverlay toActivate = getOverlay(act); | ||
| 58 | + if (toDeactivate != null) { | ||
| 59 | + toDeactivate.deactivate(); | ||
| 60 | + } | ||
| 61 | + if (toActivate != null) { | ||
| 62 | + toActivate.activate(); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + private UiTopoOverlay getOverlay(String id) { | ||
| 67 | + return id == null ? null : overlays.get(id); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * Returns the number of overlays in the cache. | ||
| 72 | + * | ||
| 73 | + * @return number of overlays | ||
| 74 | + */ | ||
| 75 | + public int size() { | ||
| 76 | + return overlays.size(); | ||
| 77 | + } | ||
| 78 | +} |
| ... | @@ -103,6 +103,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -103,6 +103,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 103 | private static final String SPRITE_DATA_REQ = "spriteDataRequest"; | 103 | private static final String SPRITE_DATA_REQ = "spriteDataRequest"; |
| 104 | private static final String TOPO_START = "topoStart"; | 104 | private static final String TOPO_START = "topoStart"; |
| 105 | private static final String TOPO_HEARTBEAT = "topoHeartbeat"; | 105 | private static final String TOPO_HEARTBEAT = "topoHeartbeat"; |
| 106 | + private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay"; | ||
| 106 | private static final String TOPO_STOP = "topoStop"; | 107 | private static final String TOPO_STOP = "topoStop"; |
| 107 | 108 | ||
| 108 | 109 | ||
| ... | @@ -135,6 +136,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -135,6 +136,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 135 | private final ExecutorService msgSender = | 136 | private final ExecutorService msgSender = |
| 136 | newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender")); | 137 | newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender")); |
| 137 | 138 | ||
| 139 | + private TopoOverlayCache overlayCache; | ||
| 140 | + | ||
| 138 | private TimerTask trafficTask = null; | 141 | private TimerTask trafficTask = null; |
| 139 | private TrafficEvent trafficEvent = null; | 142 | private TrafficEvent trafficEvent = null; |
| 140 | 143 | ||
| ... | @@ -172,6 +175,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -172,6 +175,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 172 | return ImmutableSet.of( | 175 | return ImmutableSet.of( |
| 173 | new TopoStart(), | 176 | new TopoStart(), |
| 174 | new TopoHeartbeat(), | 177 | new TopoHeartbeat(), |
| 178 | + new TopoSelectOverlay(), | ||
| 175 | new TopoStop(), | 179 | new TopoStop(), |
| 176 | new ReqSummary(), | 180 | new ReqSummary(), |
| 177 | new CancelSummary(), | 181 | new CancelSummary(), |
| ... | @@ -195,6 +199,15 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -195,6 +199,15 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 195 | ); | 199 | ); |
| 196 | } | 200 | } |
| 197 | 201 | ||
| 202 | + /** | ||
| 203 | + * Injects the topology overlay cache. | ||
| 204 | + * | ||
| 205 | + * @param overlayCache injected cache | ||
| 206 | + */ | ||
| 207 | + void setOverlayCache(TopoOverlayCache overlayCache) { | ||
| 208 | + this.overlayCache = overlayCache; | ||
| 209 | + } | ||
| 210 | + | ||
| 198 | // ================================================================== | 211 | // ================================================================== |
| 199 | 212 | ||
| 200 | /** | 213 | /** |
| ... | @@ -231,6 +244,19 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -231,6 +244,19 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 231 | } | 244 | } |
| 232 | } | 245 | } |
| 233 | 246 | ||
| 247 | + private final class TopoSelectOverlay extends RequestHandler { | ||
| 248 | + private TopoSelectOverlay() { | ||
| 249 | + super(TOPO_SELECT_OVERLAY); | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + @Override | ||
| 253 | + public void process(long sid, ObjectNode payload) { | ||
| 254 | + String deact = string(payload, "deactivate"); | ||
| 255 | + String act = string(payload, "activate"); | ||
| 256 | + overlayCache.switchOverlay(deact, act); | ||
| 257 | + } | ||
| 258 | + } | ||
| 259 | + | ||
| 234 | /** | 260 | /** |
| 235 | * @deprecated in Cardinal Release | 261 | * @deprecated in Cardinal Release |
| 236 | */ | 262 | */ |
| ... | @@ -311,7 +337,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -311,7 +337,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 311 | @Override | 337 | @Override |
| 312 | public void process(long sid, ObjectNode payload) { | 338 | public void process(long sid, ObjectNode payload) { |
| 313 | String type = string(payload, "class", "unknown"); | 339 | String type = string(payload, "class", "unknown"); |
| 314 | - String id = JsonUtils.string(payload, "id"); | 340 | + String id = string(payload, "id"); |
| 315 | 341 | ||
| 316 | if (type.equals("device")) { | 342 | if (type.equals("device")) { |
| 317 | sendMessage(deviceDetails(deviceId(id), sid)); | 343 | sendMessage(deviceDetails(deviceId(id), sid)); | ... | ... |
| 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; | ||
| 19 | + | ||
| 20 | +import org.onosproject.ui.UiTopoOverlay; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Topology Overlay for network traffic. | ||
| 24 | + */ | ||
| 25 | +public class TrafficOverlay extends UiTopoOverlay { | ||
| 26 | + private static final String TRAFFIC_ID = "traffic"; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * Constructs the traffic overlay. | ||
| 30 | + */ | ||
| 31 | + public TrafficOverlay() { | ||
| 32 | + super(TRAFFIC_ID); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + // TODO : override init(), activate(), deactivate(), destroy() | ||
| 36 | +} |
| ... | @@ -30,6 +30,7 @@ import org.onosproject.mastership.MastershipService; | ... | @@ -30,6 +30,7 @@ import org.onosproject.mastership.MastershipService; |
| 30 | import org.onosproject.ui.UiExtension; | 30 | import org.onosproject.ui.UiExtension; |
| 31 | import org.onosproject.ui.UiExtensionService; | 31 | import org.onosproject.ui.UiExtensionService; |
| 32 | import org.onosproject.ui.UiMessageHandlerFactory; | 32 | import org.onosproject.ui.UiMessageHandlerFactory; |
| 33 | +import org.onosproject.ui.UiTopoOverlayFactory; | ||
| 33 | import org.onosproject.ui.UiView; | 34 | import org.onosproject.ui.UiView; |
| 34 | import org.onosproject.ui.UiViewHidden; | 35 | import org.onosproject.ui.UiViewHidden; |
| 35 | import org.onosproject.ui.impl.topo.OverlayService; | 36 | import org.onosproject.ui.impl.topo.OverlayService; |
| ... | @@ -54,6 +55,10 @@ import static org.onosproject.ui.UiView.Category.PLATFORM; | ... | @@ -54,6 +55,10 @@ import static org.onosproject.ui.UiView.Category.PLATFORM; |
| 54 | public class UiExtensionManager | 55 | public class UiExtensionManager |
| 55 | implements UiExtensionService, SpriteService, OverlayService { | 56 | implements UiExtensionService, SpriteService, OverlayService { |
| 56 | 57 | ||
| 58 | + private static final ClassLoader CL = | ||
| 59 | + UiExtensionManager.class.getClassLoader(); | ||
| 60 | + private static final String CORE = "core"; | ||
| 61 | + | ||
| 57 | private final Logger log = LoggerFactory.getLogger(getClass()); | 62 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 58 | 63 | ||
| 59 | // List of all extensions | 64 | // List of all extensions |
| ... | @@ -104,8 +109,16 @@ public class UiExtensionManager | ... | @@ -104,8 +109,16 @@ public class UiExtensionManager |
| 104 | new ClusterViewMessageHandler() | 109 | new ClusterViewMessageHandler() |
| 105 | ); | 110 | ); |
| 106 | 111 | ||
| 107 | - return new UiExtension(coreViews, messageHandlerFactory, "core", | 112 | + UiTopoOverlayFactory topoOverlayFactory = |
| 108 | - UiExtensionManager.class.getClassLoader()); | 113 | + () -> ImmutableList.of( |
| 114 | + new TrafficOverlay() | ||
| 115 | + ); | ||
| 116 | + | ||
| 117 | + return new UiExtension.Builder(CL, coreViews) | ||
| 118 | + .messageHandlerFactory(messageHandlerFactory) | ||
| 119 | + .topoOverlayFactory(topoOverlayFactory) | ||
| 120 | + .resourcePath(CORE) | ||
| 121 | + .build(); | ||
| 109 | } | 122 | } |
| 110 | 123 | ||
| 111 | @Activate | 124 | @Activate | ... | ... |
| ... | @@ -27,6 +27,7 @@ import org.onosproject.ui.UiConnection; | ... | @@ -27,6 +27,7 @@ import org.onosproject.ui.UiConnection; |
| 27 | import org.onosproject.ui.UiExtensionService; | 27 | 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.slf4j.Logger; | 31 | import org.slf4j.Logger; |
| 31 | import org.slf4j.LoggerFactory; | 32 | import org.slf4j.LoggerFactory; |
| 32 | 33 | ||
| ... | @@ -58,6 +59,7 @@ public class UiWebSocket | ... | @@ -58,6 +59,7 @@ public class UiWebSocket |
| 58 | private long lastActive = System.currentTimeMillis(); | 59 | private long lastActive = System.currentTimeMillis(); |
| 59 | 60 | ||
| 60 | private Map<String, UiMessageHandler> handlers; | 61 | private Map<String, UiMessageHandler> handlers; |
| 62 | + private TopoOverlayCache overlayCache; | ||
| 61 | 63 | ||
| 62 | /** | 64 | /** |
| 63 | * Creates a new web-socket for serving data to GUI. | 65 | * Creates a new web-socket for serving data to GUI. |
| ... | @@ -72,7 +74,7 @@ public class UiWebSocket | ... | @@ -72,7 +74,7 @@ public class UiWebSocket |
| 72 | * Issues a close on the connection. | 74 | * Issues a close on the connection. |
| 73 | */ | 75 | */ |
| 74 | synchronized void close() { | 76 | synchronized void close() { |
| 75 | - destroyHandlers(); | 77 | + destroyHandlersAndOverlays(); |
| 76 | if (connection.isOpen()) { | 78 | if (connection.isOpen()) { |
| 77 | connection.close(); | 79 | connection.close(); |
| 78 | } | 80 | } |
| ... | @@ -104,7 +106,7 @@ public class UiWebSocket | ... | @@ -104,7 +106,7 @@ public class UiWebSocket |
| 104 | this.connection = connection; | 106 | this.connection = connection; |
| 105 | this.control = (FrameConnection) connection; | 107 | this.control = (FrameConnection) connection; |
| 106 | try { | 108 | try { |
| 107 | - createHandlers(); | 109 | + createHandlersAndOverlays(); |
| 108 | sendInstanceData(); | 110 | sendInstanceData(); |
| 109 | log.info("GUI client connected"); | 111 | log.info("GUI client connected"); |
| 110 | 112 | ||
| ... | @@ -118,7 +120,7 @@ public class UiWebSocket | ... | @@ -118,7 +120,7 @@ public class UiWebSocket |
| 118 | 120 | ||
| 119 | @Override | 121 | @Override |
| 120 | public synchronized void onClose(int closeCode, String message) { | 122 | public synchronized void onClose(int closeCode, String message) { |
| 121 | - destroyHandlers(); | 123 | + destroyHandlersAndOverlays(); |
| 122 | log.info("GUI client disconnected [close-code={}, message={}]", | 124 | log.info("GUI client disconnected [close-code={}, message={}]", |
| 123 | closeCode, message); | 125 | closeCode, message); |
| 124 | } | 126 | } |
| ... | @@ -131,6 +133,7 @@ public class UiWebSocket | ... | @@ -131,6 +133,7 @@ public class UiWebSocket |
| 131 | 133 | ||
| 132 | @Override | 134 | @Override |
| 133 | public void onMessage(String data) { | 135 | public void onMessage(String data) { |
| 136 | + log.debug("onMessage: {}", data); | ||
| 134 | lastActive = System.currentTimeMillis(); | 137 | lastActive = System.currentTimeMillis(); |
| 135 | try { | 138 | try { |
| 136 | ObjectNode message = (ObjectNode) mapper.reader().readTree(data); | 139 | ObjectNode message = (ObjectNode) mapper.reader().readTree(data); |
| ... | @@ -172,8 +175,11 @@ public class UiWebSocket | ... | @@ -172,8 +175,11 @@ public class UiWebSocket |
| 172 | } | 175 | } |
| 173 | 176 | ||
| 174 | // Creates new message handlers. | 177 | // Creates new message handlers. |
| 175 | - private synchronized void createHandlers() { | 178 | + private synchronized void createHandlersAndOverlays() { |
| 179 | + log.debug("creating handlers and overlays..."); | ||
| 176 | handlers = new HashMap<>(); | 180 | handlers = new HashMap<>(); |
| 181 | + overlayCache = new TopoOverlayCache(); | ||
| 182 | + | ||
| 177 | UiExtensionService service = directory.get(UiExtensionService.class); | 183 | UiExtensionService service = directory.get(UiExtensionService.class); |
| 178 | service.getExtensions().forEach(ext -> { | 184 | service.getExtensions().forEach(ext -> { |
| 179 | UiMessageHandlerFactory factory = ext.messageHandlerFactory(); | 185 | UiMessageHandlerFactory factory = ext.messageHandlerFactory(); |
| ... | @@ -181,15 +187,33 @@ public class UiWebSocket | ... | @@ -181,15 +187,33 @@ public class UiWebSocket |
| 181 | factory.newHandlers().forEach(handler -> { | 187 | factory.newHandlers().forEach(handler -> { |
| 182 | handler.init(this, directory); | 188 | handler.init(this, directory); |
| 183 | handler.messageTypes().forEach(type -> handlers.put(type, handler)); | 189 | handler.messageTypes().forEach(type -> handlers.put(type, handler)); |
| 190 | + | ||
| 191 | + // need to inject the overlay cache into topology message handler | ||
| 192 | + if (handler instanceof TopologyViewMessageHandler) { | ||
| 193 | + ((TopologyViewMessageHandler) handler).setOverlayCache(overlayCache); | ||
| 194 | + } | ||
| 184 | }); | 195 | }); |
| 185 | } | 196 | } |
| 197 | + | ||
| 198 | + UiTopoOverlayFactory overlayFactory = ext.topoOverlayFactory(); | ||
| 199 | + if (overlayFactory != null) { | ||
| 200 | + overlayFactory.newOverlays().forEach(overlayCache::add); | ||
| 201 | + } | ||
| 186 | }); | 202 | }); |
| 203 | + log.debug("#handlers = {}, #overlays = {}", handlers.size(), | ||
| 204 | + overlayCache.size()); | ||
| 187 | } | 205 | } |
| 188 | 206 | ||
| 189 | // Destroys message handlers. | 207 | // Destroys message handlers. |
| 190 | - private synchronized void destroyHandlers() { | 208 | + private synchronized void destroyHandlersAndOverlays() { |
| 209 | + log.debug("destroying handlers and overlays..."); | ||
| 191 | handlers.forEach((type, handler) -> handler.destroy()); | 210 | handlers.forEach((type, handler) -> handler.destroy()); |
| 192 | handlers.clear(); | 211 | handlers.clear(); |
| 212 | + | ||
| 213 | + if (overlayCache != null) { | ||
| 214 | + overlayCache.destroy(); | ||
| 215 | + overlayCache = null; | ||
| 216 | + } | ||
| 193 | } | 217 | } |
| 194 | 218 | ||
| 195 | // Sends cluster node/instance information to allow GUI to fail-over. | 219 | // Sends cluster node/instance information to allow GUI to fail-over. | ... | ... |
| ... | @@ -30,10 +30,11 @@ | ... | @@ -30,10 +30,11 @@ |
| 30 | var tos = 'TopoOverlayService: '; | 30 | var tos = 'TopoOverlayService: '; |
| 31 | 31 | ||
| 32 | // injected refs | 32 | // injected refs |
| 33 | - var $log, fs, gs; | 33 | + var $log, fs, gs, wss; |
| 34 | 34 | ||
| 35 | // internal state | 35 | // internal state |
| 36 | - var overlays = {}; | 36 | + var overlays = {}, |
| 37 | + current = null; | ||
| 37 | 38 | ||
| 38 | function error(fn, msg) { | 39 | function error(fn, msg) { |
| 39 | $log.error(tos + fn + '(): ' + msg); | 40 | $log.error(tos + fn + '(): ' + msg); |
| ... | @@ -108,20 +109,42 @@ | ... | @@ -108,20 +109,42 @@ |
| 108 | return overlays[id]; | 109 | return overlays[id]; |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 112 | + // an overlay was selected via toolbar radio button press from user | ||
| 113 | + function tbSelection(id) { | ||
| 114 | + var same = current && current.overlayId === id, | ||
| 115 | + payload = {}; | ||
| 116 | + | ||
| 117 | + function doop(op) { | ||
| 118 | + var oid = current.overlayId; | ||
| 119 | + $log.debug('Overlay:', op, oid); | ||
| 120 | + current[op](); | ||
| 121 | + payload[op] = oid; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + if (!same) { | ||
| 125 | + current && doop('deactivate'); | ||
| 126 | + current = overlay(id); | ||
| 127 | + current && doop('activate'); | ||
| 128 | + wss.sendEvent('topoSelectOverlay', payload); | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 111 | angular.module('ovTopo') | 132 | angular.module('ovTopo') |
| 112 | .factory('TopoOverlayService', | 133 | .factory('TopoOverlayService', |
| 113 | - ['$log', 'FnService', 'GlyphService', | 134 | + ['$log', 'FnService', 'GlyphService', 'WebSocketService', |
| 114 | 135 | ||
| 115 | - function (_$log_, _fs_, _gs_) { | 136 | + function (_$log_, _fs_, _gs_, _wss_) { |
| 116 | $log = _$log_; | 137 | $log = _$log_; |
| 117 | fs = _fs_; | 138 | fs = _fs_; |
| 118 | gs = _gs_; | 139 | gs = _gs_; |
| 140 | + wss = _wss_; | ||
| 119 | 141 | ||
| 120 | return { | 142 | return { |
| 121 | register: register, | 143 | register: register, |
| 122 | unregister: unregister, | 144 | unregister: unregister, |
| 123 | list: list, | 145 | list: list, |
| 124 | - overlay: overlay | 146 | + overlay: overlay, |
| 147 | + tbSelection: tbSelection | ||
| 125 | } | 148 | } |
| 126 | }]); | 149 | }]); |
| 127 | 150 | ... | ... |
| ... | @@ -50,14 +50,14 @@ | ... | @@ -50,14 +50,14 @@ |
| 50 | L: { id: 'cycleLabels-btn', gid: 'cycleLabels' }, | 50 | L: { id: 'cycleLabels-btn', gid: 'cycleLabels' }, |
| 51 | R: { id: 'resetZoom-btn', gid: 'resetZoom' }, | 51 | R: { id: 'resetZoom-btn', gid: 'resetZoom' }, |
| 52 | 52 | ||
| 53 | + E: { id: 'eqMaster-btn', gid: 'eqMaster' }, | ||
| 54 | + | ||
| 53 | V: { id: 'relatedIntents-btn', gid: 'relatedIntents' }, | 55 | V: { id: 'relatedIntents-btn', gid: 'relatedIntents' }, |
| 54 | leftArrow: { id: 'prevIntent-btn', gid: 'prevIntent' }, | 56 | leftArrow: { id: 'prevIntent-btn', gid: 'prevIntent' }, |
| 55 | rightArrow: { id: 'nextIntent-btn', gid: 'nextIntent' }, | 57 | rightArrow: { id: 'nextIntent-btn', gid: 'nextIntent' }, |
| 56 | W: { id: 'intentTraffic-btn', gid: 'intentTraffic' }, | 58 | W: { id: 'intentTraffic-btn', gid: 'intentTraffic' }, |
| 57 | A: { id: 'allTraffic-btn', gid: 'allTraffic' }, | 59 | A: { id: 'allTraffic-btn', gid: 'allTraffic' }, |
| 58 | - F: { id: 'flows-btn', gid: 'flows' }, | 60 | + F: { id: 'flows-btn', gid: 'flows' } |
| 59 | - | ||
| 60 | - E: { id: 'eqMaster-btn', gid: 'eqMaster' } | ||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | // initial toggle state: default settings and tag to key mapping | 63 | // initial toggle state: default settings and tag to key mapping |
| ... | @@ -153,14 +153,6 @@ | ... | @@ -153,14 +153,6 @@ |
| 153 | addButton('E'); | 153 | addButton('E'); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | - function setOverlay(overlayId) { | ||
| 157 | - if (!overlayId) { | ||
| 158 | - $log.debug('CLEAR overlay'); | ||
| 159 | - } else { | ||
| 160 | - $log.debug('SET overlay', overlayId); | ||
| 161 | - } | ||
| 162 | - } | ||
| 163 | - | ||
| 164 | function addOverlays() { | 156 | function addOverlays() { |
| 165 | toolbar.addSeparator(); | 157 | toolbar.addSeparator(); |
| 166 | 158 | ||
| ... | @@ -168,7 +160,9 @@ | ... | @@ -168,7 +160,9 @@ |
| 168 | var rset = [{ | 160 | var rset = [{ |
| 169 | gid: 'unknown', | 161 | gid: 'unknown', |
| 170 | tooltip: 'No Overlay', | 162 | tooltip: 'No Overlay', |
| 171 | - cb: function () { setOverlay(); } | 163 | + cb: function () { |
| 164 | + tov.tbSelection(null); | ||
| 165 | + } | ||
| 172 | }]; | 166 | }]; |
| 173 | 167 | ||
| 174 | tov.list().forEach(function (key) { | 168 | tov.list().forEach(function (key) { |
| ... | @@ -177,7 +171,7 @@ | ... | @@ -177,7 +171,7 @@ |
| 177 | gid: ov._glyphId, | 171 | gid: ov._glyphId, |
| 178 | tooltip: (ov.tooltip || '(no tooltip)'), | 172 | tooltip: (ov.tooltip || '(no tooltip)'), |
| 179 | cb: function () { | 173 | cb: function () { |
| 180 | - setOverlay(ov.overlayId); | 174 | + tov.tbSelection(ov.overlayId); |
| 181 | } | 175 | } |
| 182 | }); | 176 | }); |
| 183 | }); | 177 | }); |
| ... | @@ -186,6 +180,7 @@ | ... | @@ -186,6 +180,7 @@ |
| 186 | } | 180 | } |
| 187 | 181 | ||
| 188 | // TODO: 3rd row needs to be swapped in/out based on selected overlay | 182 | // TODO: 3rd row needs to be swapped in/out based on selected overlay |
| 183 | + // NOTE: This particular row of buttons is for the traffic overlay | ||
| 189 | function addThirdRow() { | 184 | function addThirdRow() { |
| 190 | addButton('V'); | 185 | addButton('V'); |
| 191 | addButton('leftArrow'); | 186 | addButton('leftArrow'); | ... | ... |
-
Please register or login to post a comment