summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/pathpainter
diff options
context:
space:
mode:
authorAshlee Young <ashlee@wildernessvoice.com>2015-12-06 07:15:03 -0800
committerAshlee Young <ashlee@wildernessvoice.com>2015-12-08 10:55:21 -0800
commit76dc892491948adae5e5e62cf94448967e8d865b (patch)
tree7a33ef05cc583946db21edad627060f280a53549 /framework/src/onos/apps/pathpainter
parentd333c63fdec8b064184b0a26f8d777f267577fde (diff)
Fixes bad POM file with ONOS commit 8c68536972f63069c263635c9d9f4f31d7f3e9a2
Change-Id: I7adb5a2d3738d53dbc41db7577768b0e7ced5450 Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/apps/pathpainter')
-rw-r--r--framework/src/onos/apps/pathpainter/pom.xml38
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java51
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java30
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java86
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java388
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java56
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java20
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css2
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html4
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js119
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js260
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html1
-rw-r--r--framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html2
13 files changed, 1057 insertions, 0 deletions
diff --git a/framework/src/onos/apps/pathpainter/pom.xml b/framework/src/onos/apps/pathpainter/pom.xml
new file mode 100644
index 00000000..c14294c8
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2014 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-pp</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>Path visualization application</description>
+
+ <properties>
+ <onos.app.name>org.onosproject.pathpainter</onos.app.name>
+ </properties>
+
+</project>
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java
new file mode 100644
index 00000000..57241705
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pathpainter;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+import org.onosproject.ui.topo.BiLink;
+import org.onosproject.ui.topo.LinkHighlight;
+import org.onosproject.ui.topo.LinkHighlight.Flavor;
+
+import java.util.Set;
+
+/**
+ * Bi-directional link capable of different hilights.
+ */
+public class PathLink extends BiLink {
+
+ private boolean primary = false;
+ private boolean secondary = false;
+
+ public PathLink(LinkKey key, Link link) {
+ super(key, link);
+ }
+
+ public void computeHilight(Set<Link> selectedLinks, Set<Link> allLinks) {
+ primary = selectedLinks.contains(this.one()) ||
+ (two() != null && selectedLinks.contains(two()));
+ secondary = allLinks.contains(this.one()) ||
+ (two() != null && allLinks.contains(two()));
+ }
+
+ @Override
+ public LinkHighlight highlight(Enum<?> anEnum) {
+ Flavor flavor = primary ? Flavor.PRIMARY_HIGHLIGHT :
+ (secondary ? Flavor.SECONDARY_HIGHLIGHT : Flavor.NO_HIGHLIGHT);
+ return new LinkHighlight(this.linkId(), flavor);
+ }
+}
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java
new file mode 100644
index 00000000..9f2ea216
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pathpainter;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+import org.onosproject.ui.topo.BiLinkMap;
+
+/**
+ * Our concrete link map.
+ */
+public class PathLinkMap extends BiLinkMap<PathLink> {
+ @Override
+ protected PathLink create(LinkKey linkKey, Link link) {
+ return new PathLink(linkKey, link);
+ }
+}
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java
new file mode 100644
index 00000000..07ce3fe8
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pathpainter;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.ui.UiExtension;
+import org.onosproject.ui.UiExtensionService;
+import org.onosproject.ui.UiMessageHandlerFactory;
+import org.onosproject.ui.UiTopoOverlayFactory;
+import org.onosproject.ui.UiView;
+import org.onosproject.ui.UiViewHidden;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Skeletal ONOS UI Topology-Overlay application component.
+ */
+@Component(immediate = true)
+public class PathPainter {
+
+ private static final ClassLoader CL = PathPainter.class.getClassLoader();
+ private static final String VIEW_ID = "ppTopov";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected UiExtensionService uiExtensionService;
+
+ // List of application views
+ private final List<UiView> uiViews = ImmutableList.of(
+ new UiViewHidden(VIEW_ID)
+ );
+
+ // Factory for UI message handlers
+ private final UiMessageHandlerFactory messageHandlerFactory =
+ () -> ImmutableList.of(
+ new PathPainterTopovMessageHandler()
+ );
+
+ // Factory for UI topology overlays
+ private final UiTopoOverlayFactory topoOverlayFactory =
+ () -> ImmutableList.of(
+ new PathPainterTopovOverlay()
+ );
+
+ // Application UI extension
+ protected UiExtension extension =
+ new UiExtension.Builder(CL, uiViews)
+ .resourcePath(VIEW_ID)
+ .messageHandlerFactory(messageHandlerFactory)
+ .topoOverlayFactory(topoOverlayFactory)
+ .build();
+
+ @Activate
+ protected void activate() {
+ uiExtensionService.register(extension);
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ uiExtensionService.unregister(extension);
+ log.info("Stopped");
+ }
+
+}
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java
new file mode 100644
index 00000000..cf395e49
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pathpainter;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.DisjointPath;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.topology.GeoDistanceLinkWeight;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.PathService;
+import org.onosproject.net.topology.TopologyEvent;
+import org.onosproject.net.topology.TopologyListener;
+import org.onosproject.net.topology.TopologyService;
+import org.onosproject.ui.RequestHandler;
+import org.onosproject.ui.UiConnection;
+import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.topo.DeviceHighlight;
+import org.onosproject.ui.topo.Highlights;
+import org.onosproject.ui.topo.HostHighlight;
+import org.onosproject.ui.topo.NodeBadge;
+import org.onosproject.ui.topo.TopoJson;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Skeletal ONOS UI Topology-Overlay message handler.
+ */
+public class PathPainterTopovMessageHandler extends UiMessageHandler {
+
+ private static final String PAINTER_CLEAR = "ppTopovClear";
+ private static final String PAINTER_SET_SRC = "ppTopovSetSrc";
+ private static final String PAINTER_SET_DST = "ppTopovSetDst";
+ private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst";
+ private static final String PAINTER_SET_MODE = "ppTopovSetMode";
+
+ private static final String PAINTER_NEXT_PATH = "ppTopovNextPath";
+ private static final String PAINTER_PREV_PATH = "ppTopovPrevPath";
+
+ private static final String ID = "id";
+ private static final String MODE = "mode";
+ private static final String TYPE = "type";
+ private static final String SWITCH = "switch";
+ private static final String ENDSTATION = "endstation";
+ public static final String DST = "Dst";
+ public static final String SRC = "Src";
+ private static LinkWeight linkData;
+
+ private final TopologyListener topologyListener = new InternalTopologyListener();
+
+ private Set<Link> allPathLinks;
+ private boolean listenersRemoved;
+
+ private enum Mode {
+ SHORTEST, DISJOINT, GEODATA, SRLG, INVALID
+ }
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private PathService pathService;
+
+ private ElementId src, dst;
+ private String srcType, dstType;
+ private Mode currentMode = Mode.SHORTEST;
+ private List<Path> paths;
+ private int pathIndex;
+
+ protected TopologyService topologyService;
+
+
+ // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================
+
+
+ @Override
+ public void init(UiConnection connection, ServiceDirectory directory) {
+ super.init(connection, directory);
+ pathService = directory.get(PathService.class);
+ topologyService = directory.get(TopologyService.class);
+ linkData = new GeoDistanceLinkWeight(directory.get(DeviceService.class));
+ addListeners();
+ }
+
+
+ @Override
+ public void destroy() {
+ removeListeners();
+ super.destroy();
+ }
+
+ @Override
+ protected Collection<RequestHandler> createRequestHandlers() {
+ return ImmutableSet.of(
+ new ClearHandler(),
+ new SetSrcHandler(),
+ new SetDstHandler(),
+ new SwapSrcDstHandler(),
+ new NextPathHandler(),
+ new PrevPathHandler(),
+ new SetModeHandler()
+ );
+ }
+
+ // === -------------------------
+ // === Handler classes
+
+ private final class ClearHandler extends RequestHandler {
+
+ public ClearHandler() {
+ super(PAINTER_CLEAR);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ src = null;
+ dst = null;
+ sendMessage(TopoJson.highlightsMessage(new Highlights()));
+ }
+ }
+
+ private final class SetSrcHandler extends RequestHandler {
+
+ public SetSrcHandler() {
+ super(PAINTER_SET_SRC);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ String id = string(payload, ID);
+ src = elementId(id);
+ srcType = string(payload, TYPE);
+ if (src.equals(dst)) {
+ dst = null;
+ }
+ sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
+ srcType,
+ src.toString(),
+ SRC)));
+ findAndSendPaths(currentMode);
+ }
+ }
+
+ private final class SetDstHandler extends RequestHandler {
+ public SetDstHandler() {
+ super(PAINTER_SET_DST);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ String id = string(payload, ID);
+ dst = elementId(id);
+ dstType = string(payload, TYPE);
+ if (src.equals(dst)) {
+ src = null;
+ }
+
+ sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
+ dstType,
+ dst.toString(),
+ DST)));
+ findAndSendPaths(currentMode);
+ }
+ }
+
+ private final class SwapSrcDstHandler extends RequestHandler {
+ public SwapSrcDstHandler() {
+ super(PAINTER_SWAP_SRC_DST);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ ElementId temp = src;
+ src = dst;
+ dst = temp;
+ String s = srcType;
+ srcType = dstType;
+ dstType = s;
+ findAndSendPaths(currentMode);
+ }
+ }
+
+
+
+ private final class NextPathHandler extends RequestHandler {
+ public NextPathHandler() {
+ super(PAINTER_NEXT_PATH);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1);
+ hilightAndSendPaths();
+ }
+ }
+
+ private final class PrevPathHandler extends RequestHandler {
+ public PrevPathHandler() {
+ super(PAINTER_PREV_PATH);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1);
+ hilightAndSendPaths();
+ }
+ }
+
+ private final class SetModeHandler extends RequestHandler {
+ public SetModeHandler() {
+ super(PAINTER_SET_MODE);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ String mode = string(payload, MODE);
+ switch (mode) {
+ case "shortest":
+ currentMode = Mode.SHORTEST;
+ break;
+ case "disjoint":
+ currentMode = Mode.DISJOINT;
+ break;
+ case "geodata":
+ currentMode = Mode.GEODATA;
+ break;
+ case "srlg":
+ currentMode = Mode.SRLG;
+ break;
+ default:
+ currentMode = Mode.INVALID;
+ break;
+ }
+ //TODO: add support for SRLG
+ findAndSendPaths(currentMode);
+ }
+ }
+
+ // === ------------
+
+ private ElementId elementId(String id) {
+ try {
+ return DeviceId.deviceId(id);
+ } catch (IllegalArgumentException e) {
+ return HostId.hostId(id);
+ }
+ }
+
+ private void findAndSendPaths(Mode mode) {
+ log.info("src={}; dst={}; mode={}", src, dst, currentMode);
+ if (src != null && dst != null) {
+ pathIndex = 0;
+ ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
+ if (mode.equals(Mode.SHORTEST)) {
+ paths = ImmutableList.copyOf(pathService.getPaths(src, dst));
+ allPathLinks = buildPaths(builder).build();
+ } else if (mode.equals(Mode.DISJOINT)) {
+ paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst));
+ allPathLinks = buildDisjointPaths(builder).build();
+ } else if (mode.equals(Mode.GEODATA)) {
+ paths = ImmutableList.copyOf(pathService.getPaths(src, dst, linkData));
+ allPathLinks = buildPaths(builder).build();
+ } else {
+ log.info("Unsupported MODE");
+ }
+ } else {
+ paths = ImmutableList.of();
+ allPathLinks = ImmutableSet.of();
+ }
+ hilightAndSendPaths();
+
+ }
+
+ private ImmutableSet.Builder<Link> buildPaths(ImmutableSet.Builder<Link> pathBuilder) {
+ paths.forEach(path -> path.links().forEach(pathBuilder::add));
+ return pathBuilder;
+ }
+
+ private ImmutableSet.Builder<Link> buildDisjointPaths(ImmutableSet.Builder<Link> pathBuilder) {
+ paths.forEach(path -> {
+ DisjointPath dp = (DisjointPath) path;
+ pathBuilder.addAll(dp.primary().links());
+ pathBuilder.addAll(dp.backup().links());
+ });
+ return pathBuilder;
+ }
+
+ private void hilightAndSendPaths() {
+ PathLinkMap linkMap = new PathLinkMap();
+ allPathLinks.forEach(linkMap::add);
+
+ Set<Link> selectedPathLinks;
+
+ // Prepare two working sets; one containing selected path links and
+ // the other containing all paths links.
+ if (currentMode.equals(Mode.DISJOINT)) {
+ DisjointPath dp = (DisjointPath) paths.get(pathIndex);
+ selectedPathLinks = paths.isEmpty() ?
+ ImmutableSet.of() : Sets.newHashSet(dp.primary().links());
+ selectedPathLinks.addAll(dp.backup().links());
+ } else {
+ selectedPathLinks = paths.isEmpty() ?
+ ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links());
+ }
+ Highlights highlights = new Highlights();
+ for (PathLink plink : linkMap.biLinks()) {
+ plink.computeHilight(selectedPathLinks, allPathLinks);
+ highlights.add(plink.highlight(null));
+ }
+ if (src != null) {
+ highlights = addBadge(highlights, srcType, src.toString(), SRC);
+ }
+ if (dst != null) {
+ highlights = addBadge(highlights, dstType, dst.toString(), DST);
+ }
+ sendMessage(TopoJson.highlightsMessage(highlights));
+ }
+
+ private Highlights addBadge(Highlights highlights, String type, String elemId, String src) {
+ if (SWITCH.equals(type)) {
+ highlights = addDeviceBadge(highlights, elemId, src);
+ } else if (ENDSTATION.equals(type)) {
+ highlights = addHostBadge(highlights, elemId, src);
+ }
+ return highlights;
+ }
+
+ private Highlights addDeviceBadge(Highlights h, String elemId, String type) {
+ DeviceHighlight dh = new DeviceHighlight(elemId);
+ dh.setBadge(createBadge(type));
+ h.add(dh);
+ return h;
+ }
+
+ private Highlights addHostBadge(Highlights h, String elemId, String type) {
+ HostHighlight hh = new HostHighlight(elemId);
+ hh.setBadge(createBadge(type));
+ h.add(hh);
+ return h;
+ }
+
+ private NodeBadge createBadge(String type) {
+ return NodeBadge.text(type);
+ }
+
+ private synchronized void addListeners() {
+ listenersRemoved = false;
+ topologyService.addListener(topologyListener);
+ }
+ private synchronized void removeListeners() {
+ if (!listenersRemoved) {
+ listenersRemoved = true;
+ topologyService.removeListener(topologyListener);
+ }
+ }
+
+ // Link event listener.
+ private class InternalTopologyListener implements TopologyListener {
+ @Override
+ public void event(TopologyEvent event) {
+ findAndSendPaths(currentMode);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java
new file mode 100644
index 00000000..78f5f905
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014,2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pathpainter;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.ui.UiTopoOverlay;
+import org.onosproject.ui.topo.ButtonId;
+import org.onosproject.ui.topo.PropertyPanel;
+
+/**
+ * Our topology overlay.
+ */
+public class PathPainterTopovOverlay extends UiTopoOverlay {
+
+ // NOTE: this must match the ID defined in ppTopovOverlay.js
+ private static final String OVERLAY_ID = "pp-overlay";
+
+ private static final ButtonId SRC_BUTTON = new ButtonId("src");
+ private static final ButtonId DST_BUTTON = new ButtonId("dst");
+
+ public PathPainterTopovOverlay() {
+ super(OVERLAY_ID);
+ }
+
+ @Override
+ public void deactivate() {
+ super.deactivate();
+ log.debug("PathPainterOverlay Deactivated");
+ }
+
+ @Override
+ public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) {
+ pp.addButton(SRC_BUTTON).addButton(DST_BUTTON);
+ }
+
+ @Override
+ public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
+ pp.addButton(SRC_BUTTON).addButton(DST_BUTTON);
+ }
+
+
+}
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java
new file mode 100644
index 00000000..e625933b
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Path visualization GUI topology view overlay.
+ */
+package org.onosproject.pathpainter; \ No newline at end of file
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css
new file mode 100644
index 00000000..cbf460f9
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css
@@ -0,0 +1,2 @@
+/* css for sample app topology overlay */
+
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html
new file mode 100644
index 00000000..9141975f
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html
@@ -0,0 +1,4 @@
+<!-- partial HTML -->
+<div id="ov-pp-topov">
+ <p>This is a hidden view .. just a placeholder to house the javascript</p>
+</div>
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js
new file mode 100644
index 00000000..baaaef98
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ Sample Demo module. This contains the "business logic" for the topology
+ overlay that we are implementing.
+ */
+
+(function () {
+ 'use strict';
+
+ // injected refs
+ var $log, fs, flash, wss;
+
+ // constants
+ var srcMessage = 'ppTopovSetSrc',
+ dstMessage = 'ppTopovSetDst',
+ swapMessage = 'ppTopovSwapSrcDst',
+ modeMessage = 'ppTopovSetMode',
+ nextPathMessage = 'ppTopovNextPath',
+ clearMessage = 'ppTopovClear',
+ prevPathMessage = 'ppTopovPrevPath';
+
+ // internal state
+ var currentMode = null;
+
+
+ // === ---------------------------
+ // === Helper functions
+
+
+ // === ---------------------------
+ // === Main API functions
+
+ function clear() {
+ wss.sendEvent(clearMessage);
+ flash.flash('Source node: ' + node.id);
+ }
+
+ function setSrc(node) {
+ wss.sendEvent(srcMessage, {
+ id: node.id,
+ type: node.type
+ });
+ flash.flash('Source node: ' + node.id);
+ }
+
+ function setDst(node) {
+ wss.sendEvent(dstMessage, {
+ id: node.id,
+ type: node.type
+ });
+ flash.flash('Destination node: ' + node.id);
+ }
+
+ function swapSrcDst() {
+ wss.sendEvent(swapMessage)
+ flash.flash('Source and destination swap');
+ }
+
+ function nextPath() {
+ wss.sendEvent(nextPathMessage);
+ }
+
+ function prevPath() {
+ wss.sendEvent(prevPathMessage);
+ }
+
+
+ function setMode(mode) {
+ if (currentMode === mode) {
+ $log.debug('(in mode', mode, 'already)');
+ flash.flash('Already in ' + mode + ' mode');
+ } else {
+ currentMode = mode;
+ wss.sendEvent(modeMessage, {
+ mode: mode
+ });
+ flash.flash('Path mode: ' + mode);
+ }
+ }
+
+ // === ---------------------------
+ // === Module Factory Definition
+
+ angular.module('ovPpTopov', [])
+ .factory('PathPainterTopovService',
+ ['$log', 'FnService', 'FlashService', 'WebSocketService',
+
+ function (_$log_, _fs_, _flash_, _wss_) {
+ $log = _$log_;
+ fs = _fs_;
+ flash = _flash_;
+ wss = _wss_;
+
+ return {
+ setSrc: setSrc,
+ setDst: setDst,
+ setMode: setMode,
+ nextPath: nextPath,
+ prevPath: prevPath,
+ swapSrcDst: swapSrcDst,
+ clear: clear
+ };
+ }]);
+}());
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js
new file mode 100644
index 00000000..f98ed2b7
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js
@@ -0,0 +1,260 @@
+// path painter topology overlay - client side
+//
+// This is the glue that binds our business logic (in ppTopovDemo.js)
+// to the overlay framework.
+
+(function () {
+ 'use strict';
+
+ // injected refs
+ var $log, tov, pps;
+
+ // internal state should be kept in the service module (not here)
+ var selection;
+
+ // our overlay definition
+ var overlay = {
+ // NOTE: this must match the ID defined in AppUiTopovOverlay
+ overlayId: 'pp-overlay',
+ glyphId: 'topo',
+ tooltip: 'Path Painter Topo Overlay',
+
+ activate: function () {
+ $log.debug("Path painter topology overlay ACTIVATED");
+ },
+ deactivate: function () {
+ pps.clear();
+ $log.debug("Path painter topology overlay DEACTIVATED");
+ },
+ // These glyphs get installed using the overlayId as a prefix.
+ // e.g. 'src' is installed as 'pp-overlay-src'
+ // They can be referenced (from this overlay) as '*src'
+ // That is, the '*' prefix stands in for 'pp-overlay-'
+ glyphs: {
+ src: {
+ vb: '0 0 110 110',
+ d: 'M28.7,59.3 M14.9,53 M8.7,39 M32.4,92.5H25l-0.2-3.6' +
+ 'c-0.5-9-5.4-23.9-12.9-33.5c-5.2-6.6-7-12.8-7-16.3c0-13.3,10.7-24,23.8-24c13.1,0,23.8,10.8,23.8,24c0,3.5-1.8,9.7-7,16.3' +
+ 'C38,65,33.1,80,32.6,88.9L32.4,92.5z M27.9,89.5h1.7l0-0.7c0.5-9.4,5.7-25.2,13.5-35.2c4.7-6,6.4-11.4,6.4-14.5' +
+ 'c0-11.6-9.3-21-20.8-21C17.3,18,7.9,27.5,7.9,39c0,3,1.7,8.4,6.4,14.5c7.9,10.1,13.1,25.8,13.5,35.2L27.9,89.5z M28.7,83.2' +
+ 'M28.6,29.8c-4.7,0-8.5,3.8-8.5,8.5c0,4.7,3.8,8.5,8.5,8.5s8.5-3.8,8.5-8.5C37.1,33.6,33.3,29.8,28.6,29.8z M89.6,47 M89.6,29.5' +
+ 'c-0.1,3.1-0.1,12.8,0,17c0.1,4.2,14.1-5.5,13.9-8.5C103.4,35.1,89.6,25.6,89.6,29.5z M51,38.1L89.5,38 M89.5,39.5l0-3L51,36.5l0,3' +
+ 'L89.5,39.5z'
+ },
+ dst: {
+ vb: '0 0 110 110',
+ d: 'M80.3,59.8 M85.8,92.5h-7.2L78.4,89c-0.4-8.8-5.2-23.6-12.3-33' +
+ 'c-4.9-6.5-6.7-12.5-6.7-16c0-13,10.2-23.7,22.7-23.7c12.5,0,22.7,10.6,22.7,23.7c0,3.5-1.8,9.5-6.7,16C91.2,65.4,86.4,80.1,86,89' +
+ 'L85.8,92.5z M81.4,89.5H83l0-0.7c0.5-9.3,5.4-24.8,12.9-34.7c4.5-5.9,6.1-11.2,6.1-14.2c0-11.4-8.9-20.7-19.8-20.7' +
+ 'c-10.9,0-19.8,9.3-19.8,20.7c0,3,1.6,8.3,6.1,14.2C76,64,80.9,79.5,81.4,88.8L81.4,89.5z M82.1,30.8c-4.5,0-8.1,3.7-8.1,8.4' +
+ 's3.6,8.4,8.1,8.4c4.5,0,8.1-3.7,8.1-8.4S86.6,30.8,82.1,30.8z M47.2,47.5 M45.2,30.8c-0.1,3.1-0.1,12.6,0,16.7' +
+ 'c0.1,4.1,13.4-5.4,13.3-8.4C58.4,36.2,45.2,26.9,45.2,30.8z M45.2,39.1L6.7,39.2 M45.2,40.6l0-3L6.7,37.7l0,3L45.2,40.6z'
+ },
+ jp: {
+ vb: '0 0 110 110',
+ d: 'M84.3,89.3L58.9,64.2l-1.4,1.4L83,90.7L84.3,89.3z M27,7.6H7.4v19.2H27V7.6z' +
+ 'M59.3,47.1H39.8v19.2h19.5V47.1z M102.1,79.5H82.6v19.2h19.5V79.5z M41.7,47.6L19,25.1l-1.2,1.2l22.7,22.5L41.7,47.6z'
+ },
+ djp: {
+ vb: '0 0 110 110',
+ d: 'M25.8,84l-9.2-57 M27.3,83.8l-9.2-57l-3,0.5l9.2,57L27.3,83.8z M83.2,37.7L26.8,15.5 M83.7,36.1L26.6,14' +
+ 'l-1,3.2l57,22.1L83.7,36.1z M34.1,95l61.4-40.6 M96.4,55.7l-1.9-2.5L33.2,93.8l1.9,2.5L96.4,55.7z M26.6,27.6H6.7V7.7h19.9V27.6z' +
+ 'M102.1,36H82.2v19.9h19.9V36z M35.3,83.5H15.3v19.9h19.9V83.5z'
+ },
+ geo: {
+ vb: '0 0 110 110',
+ d: 'M55.7,94.6c-0.1-0.3,0-1-0.1-1.4'+
+ 'c-0.7-0.5-1.3-2.2-2.1-2.6c-0.5-0.3-1.4-0.2-2-0.5c-0.3-0.1-0.6-0.3-0.9-0.4c-0.4-0.1-0.8-0.1-1.1-0.3c-1.3-0.7-1.9-3-3.5-2.9'+
+ 'c-0.7,0-1.3,0.7-1.9,0.7c-0.6,0-1.6-0.5-2.4-0.9c-0.8-0.4-1.6-0.6-2.3-1c-0.5-0.3-0.9-0.9-1.3-1.1C37.8,84,37.2,84,37,83.9'+
+ 'c-0.4-0.2-0.8-0.7-1.3-1.1c-0.5-0.4-1-0.9-1-1.4c0-0.6,0.5-1,0.5-1.6c0.2-1.7-1-2.9-1.7-3.9c-0.5-0.7-1.1-1.4-1.7-2.1'+
+ 'c0-0.5,0-0.5,0-1c-0.4-0.4-0.7-1.1-1.1-1.7c-0.4-0.6-1.1-1.2-1.2-1.9c-0.1-0.8,0.3-1.5,0-2.3c-0.5-1.3-2-0.7-1.8,1'+
+ 'c0.1,0.5,0.6,1.1,0.8,1.6c0.2,0.5,0.1,1.1,0.3,1.6c0.2,0.6,0.7,1,0.8,1.7c0.3,1,0.3,2,0.5,2.7c0.2,0.5,1,1.1,0.6,1.7'+
+ 'c-0.6,0.1-0.8-0.5-1.2-0.9c-0.2-0.2-1-0.6-1.1-1.1c-0.1-0.4,0.2-1,0.1-1.5c-0.2-1-2-1-2-2.1c0-0.7,0.8-0.7,0.8-1.4'+
+ 'c0-0.7-0.8-1.3-1-1.9c-0.2-0.5-0.2-1.4-0.3-2.2c-0.1-0.7,0-1.5-0.1-2.1c-0.1-0.5-0.8-1.2-1.2-1.4c-0.6-0.3-1-0.2-1.3-0.7'+
+ 'c-0.2-0.4-0.4-1.4-0.4-1.9c-0.1-0.9,0-1.8-0.1-2.7c0-0.9-0.1-1.8,0-2.8c0.3-0.7,0.9-1,1.2-1.7c0.2-0.5,0.3-1.1,0.5-1.6'+
+ 'c0.5-0.9,1.5-1.8,2.2-2.7c0.7-1,1.4-1.9,1.8-3.1c0.2-0.4,0.6-1.3,0.5-1.8c-0.1-0.7-1.2-1.3-1.1-2.1c0.1-0.5,0.7-0.5,0.9-1'+
+ 'c0.1-0.3,0.2-1,0.2-1.3c0-0.7-0.3-1.4-0.2-2.2c0.1-0.6,0.9-0.9,0.5-1.6c-0.4-0.7-1.2,0.4-1.7-0.1c-0.4-0.4,0.1-0.9,0.1-1.7'+
+ 'c0-0.3-0.2-0.6-0.1-0.9c0-0.3,0.6-0.9,0.4-1.1c-0.3-0.5-0.7-1.7-1.5-2.2c-0.9-0.5-1.9-0.2-3.2-0.4c-0.8-0.2-1.2-1-1.9-0.9'+
+ 'c-0.5,0-0.7,0.6-1.3,0.9c-0.6,0.3-1.4,0.2-2,0.4c-0.6,0.2-0.9,0.6-1.5,0.6c-0.5,0-0.5-0.6-1.1-0.6c-0.2,0-0.7,0.2-1.1,0.2'+
+ 'c-1,0.1-2.8,0.2-3.7-0.1c-0.9-0.2-1.5-0.5-2.5-1.1C7.4,28.2,6,27.7,6.1,27c0-0.4,1.3-0.8,1.8-1c0.8-0.3,1.3-0.7,2-0.8'+
+ 'c0.2,0,0.6,0.2,0.9,0.1c0.3,0,0.7-0.4,1.1-0.4c0.9-0.1,2.1,0.1,2-0.9c-0.7-0.6-3.4,0.4-3.5-0.9c0-0.8,1-1,1.8-1.2'+
+ 'c0.7-0.2,1.8-0.5,2.5-0.4c0.7,0,1.7,1,2.1-0.1c0.2-0.7-0.2-1.3-0.4-1.9c0.5-0.8,1.5-0.7,2.3-0.9c0.9-0.1,1.6-0.3,2.4-0.7'+
+ 'c0.7-0.4,1.5-0.6,2.4-0.7c0.9-0.1,1.7-0.5,2.5-0.6c0.6-0.1,1.2,0,1.8-0.1c0.5-0.1,1.1-0.5,1.7-0.4c0.4,0,0.7,0.4,1.1,0.4'+
+ 'c0.4,0.1,0.8,0,1.2,0.1c0.3,0.1,0.6,0.3,0.9,0.4c0.5,0.1,1-0.1,1.5,0c0.4,0.1,0.8,0.4,1.2,0.4c1,0.1,2.1-0.1,3.1,0.1'+
+ 'c0.4,0.1,0.7,0.3,1.1,0.4c0.4,0.1,0.8,0,1.1,0.1c0.5,0.1,0.9,0.7,1.5,0.7c1,0.1,2.1-0.5,3.1-0.6c0.7-0.1,1.5,0,2.3-0.1'+
+ 'c0.7-0.2,1.4-0.5,2-0.5c0.3,0,0.6,0.1,1,0.1c0.3,0,0.7-0.5,1.1-0.4c0.5,0.1,0.4,0.8,0.9,0.9c0.6-0.3,1.1,0,1.7,0'+
+ 'c0.6,0,1.1-0.3,1.8-0.2c1.2,0.2,2.8,1.5,3.7,0.8c0.2-0.2,0.2-0.5,0.4-0.9c0.3-0.6,0.8-1.3,0.7-2.2c-1.3,0-2.5,0.7-3.9,0.8'+
+ 'c-1.5-1,0.4-1.7,1.5-2.2c0.9-0.4,1.6-1.3,2.7-1.4C62,12.5,63,12.9,64,13c0.6,0.1,1.2,0,1.6,0.1c0.6,0.2,0.9,0.9,1.5,1.1'+
+ 'c0.2,0.1,0.6,0.1,0.9,0.1c0.6,0.1,1.1,0.5,1.7,0c0.4,0.1,0.5,0.6,1,0.7c0.4-0.3,0.7-0.9,1.4-1.1c0.3-0.1,0.6,0.1,0.9,0'+
+ 'c0.5-0.1,1.2-0.9,1.5-0.1c-0.1,0.5-0.8,0.6-1.2,1c-0.3,0.4-0.9,1.2-0.8,1.6c0.1,0.7,1,0.4,1,1.3c-0.1,0.5-0.7,0.3-1.1,0.5'+
+ 'c-0.4,0.2-0.5,0.6-1,0.7c-1.2,0.2-2.1-0.3-3.1-0.3c0,0.5,0.5,0.8,0.8,0.9c0.9,0.5,1.6,0.5,2.9,0.4c0.7,0,1.4,0.2,2-0.2'+
+ 'c0.4-0.3,0.3-0.9,0.6-1.2c0.4-0.4,1.2-0.8,1.7-0.7c0.3,0.1,0.7,0.4,0.7,0.7c0,0.7-0.8,0.4-0.8,1.1c0.5,0.4,2-0.4,2-1'+
+ 'c0.1-0.4-0.5-0.7-0.4-1.1c0-0.8,0.9-0.7,0.8-1.5c-0.4-0.4-0.9,0.1-1.3,0c-0.6-0.1-1.2-1-1.5-1.5c0.3-0.4,0.9-0.1,1.3-0.1'+
+ 'c0.5-0.7,1.3-1,2.5-1.1c0.4,0,1-0.2,1.2,0.2c0.1,0.7-0.9,1.1-0.7,1.9c0.9,0.2,1.1-1.1,1.8-1.6c0.3-0.2,0.8-0.4,1.2-0.6'+
+ 'c0.4-0.2,0.8-0.6,1.1-0.6c0.4,0,0.4,0.3,0.8,0.5c0.3,0.1,0.7-0.1,0.8,0.4c-0.7,1.4-3.5,0.6-4.2,2.1c0.2,1-0.4,1.9,0.1,2.6'+
+ 'c0.4,0.5,1.1,0.2,1.3,0.6c0.2,0.7-0.8,0.7-0.5,1.4c0.7,0.5,1.5-0.4,2.1-0.8c0.7-0.4,1.5-0.8,1.6-1.7c-0.3-0.7-1.6-0.2-1.8-0.9'+
+ 'c-0.1-0.4,0.4-1.3,0.5-1.5c0.7-0.8,3-2,4.6-1.9c0.3,0,0.6,0.3,1,0.3c1.1,0.1,2.4-0.5,3.2,0c0.7-0.5,1.5,0.1,2.5-0.1'+
+ 'c0.7,0.5,0.5,1.5,1.7,2c0.3,0.1,0.7,0,1.1,0.1c0.3,0.1,0.6,0.5,1,0.6c0.5,0.2,0.9,0.2,1,0.6c0.1,0.4-0.3,0.6-0.3,1'+
+ 'c0.3,0.3,0,0.6,0.2,1c0.3,0.7,1,0.6,1.6,0.9c0.5,0.2,1.5,0.9,1.5,1.4c0,0.4-1,1-1.3,1.1c-0.2,0.1-1.3,0.7-1.7,0.6'+
+ 'c-0.6-0.1-0.8-1.5-1.7-1.4c-0.4,0-0.7,0.3-0.7,0.8c0,0.9,0.9,1,1,1.8c0,1-0.5,1-1.2,1.6c-0.5-0.2-1-0.6-1.7-0.6'+
+ 'c-0.4,0.5,0.7,0.7,0.3,1.4c-1,0.2-1.8-0.3-2.7-0.6c-0.3-0.1-0.7-0.1-1-0.2c-0.4-0.2-0.5-0.9-0.8-1.3c-0.3-0.4-1-1-1.6-1'+
+ 'c-0.8,0-1.9,1.1-2.5,0.1c0.4-1.6,2.5-0.4,3.8-1c0.5-0.2,0.7-0.8,1.1-1.1c0.8-0.5,2.2-0.6,2-1.7c-0.1-0.5-0.7-0.5-1.1-0.8'+
+ 'c-0.5-0.4-0.9-1.7-1.6-1.7c-0.4,0-0.6,0.3-1,0.4c-0.8,0.1-1.7-0.4-2.5,0c-0.3,0.2-0.1,0.6-0.4,1c-0.2,0.3-0.7,0.4-1,0.8'+
+ 'c-0.2,0.4-0.2,0.9-0.5,1.2c-0.5,0.5-1.6,0.6-2.3,0.9c-0.3,0.1-0.7,0.5-1,0.5c-0.5,0-0.7-0.8-1.3-0.5c0,0.8,0.7,1.1,1.2,1.4'+
+ 'c0.5,0.4,1.1,0.8,1.3,1.4c-0.5,1.2-1.3-0.1-2.2-0.1c-0.9,0-2.2,1.9-3,0.4c0.2-0.8,1-1,1.2-1.8c-0.9,0.2-1.7,1-2.7,1.3'+
+ 'c-0.4,0.1-0.9,0.1-1.3,0.2c-0.8,0.3-1.3,0.9-2.1,1.2c-0.3,0.1-0.7,0.1-1,0.2c-0.8,0.3-1.7,0.8-2.5,1.3c-0.8,0.5-1.7,1-2.2,1.5'+
+ 'c-0.3,0.3-1,1.2-1,1.5c0,0.4,0.7,0.6,0.8,1c0,0.3-0.4,0.8-0.1,1.2c0.3,0.3,0.8,0.1,1.3,0.1c1,0.1,1.6,1,2.4,1.5'+
+ 'c0.6,0.4,1.4,0.8,2,0.9c0.9,0.1,1.8-0.3,2,0.5c0.1,0.8-0.8,1-0.9,1.5c0.5,0.7-0.3,1-0.3,1.6c0,0.5,0.5,1.2,1,1.3'+
+ 'c0.6,0.1,1.6-0.7,1.8-1.4c0.3-0.9,0.2-2,0.8-2.7c3,0.1,5.5-1.5,5.3-4.9c0-0.3-0.2-0.8-0.1-1.2c0.1-0.6,0.9-1,0.8-1.7'+
+ 'c0.8-0.3,0.8-1.8,1.7-2c0.7-0.2,1.5,0.6,2.5,0.5c0.3,0,0.7-0.3,1-0.3c0.6,0.1,1,1,1.5,1.4c0.4,0.4,0.9,0.2,1,0.7'+
+ 'c-0.1,0.8-0.6,0.8-0.6,1.6c0,0.7,0.7,1.2,1,1.2c0.5,0.1,1.1-0.2,1.6-0.4c0.8-0.5,1.6-1.8,2.3-1.7c0.6,0.1,1,2.1,1.1,2.9'+
+ 'c0.1,0.8-0.1,1.4-0.1,2.1c0.1,1.2,1.4,1.1,2.1,1.7c0.2,0.2,0.3,0.7,0.4,0.9c0.3,0.5,0.7,0.5,0.8,1c0.1,1.2-1,1.3-0.9,2.7'+
+ 'c-0.2,0.5-0.8,0.5-0.8,1.2c0.1,1.1,1.5,0.3,1.9,1.1c0.2,0.5,0,0.8-0.2,1.5c0.5,0.7,0.5,1.7-0.4,1.7c-0.5,0-0.7-0.6-1.2-0.8'+
+ 'c-0.3-0.1-0.7-0.1-1.1-0.1c-0.3-0.1-0.7-0.2-1-0.2c-0.8-0.1-1.6,0.2-2.1-0.4c0.8-1.1,1.8-2.3,2.7-3.2c0.3-0.3,0.9-0.5,0.8-1.1'+
+ 'c-0.5-0.5-1.2,0-1.7,0.4c-0.5,0.3-1.2,0.8-1.8,0.9c-1.1,0.2-2.4-0.3-3.3,0.3c-0.1,0.5,1,0.3,0.8,1.1C92.8,43,92.4,43,92,42.7'+
+ 'c-0.3-0.3-0.1-0.8-0.3-0.9c-0.3-0.3-1.5-0.4-2.1-0.3c-0.7,0.1-1.3,0.6-1.3,1.2c0.8,0.4,2.1-0.4,2.4,0.6c-0.4,0.9-1.5,1.4-1.3,2.6'+
+ 'c0.1,0.5,0.5,1.1,0.9,1.1c0.3,0.1,0.5-0.3,0.9-0.3c0.4,0,0.3,0.5,0.7,0.4c0.6-0.3,1-1.3,1.7-1.2c0.8,1.2-0.8,1.7-1.7,2.1'+
+ 'c-1,0.4-2.3,0.6-3.1,1c-0.4,0.2-1.9,1.9-2.2,0.6c-0.2-0.9,0.8-0.7,1-1.4c-1-0.2-1.9,0.5-2.8,0.9c-1.3,0.5-3.4,0.9-3.8,2.5'+
+ 'c-0.1,0.3,0.1,0.9-0.1,1.1c-0.2,0.2-1.1,0.2-1.5,0.4c-0.6,0.2-1.2,0.7-1.5,0.9C77.7,54,77.2,54,77,54.1c-0.5,0.2-0.7,1-1.3,1.5'+
+ 'c-0.2,0.2-0.8,0.4-1,0.6c-0.3,0.4-0.4,1.3-1,1.4c-0.4,0-0.7-0.3-1-0.1c0,0.9,0.3,2.2-0.1,3.1c-0.8,0.7-1.6,1.2-2.5,1.8'+
+ 'c-0.5,0.3-1,0.4-1.7,0.8c-0.5,0.3-0.9,0.9-1.4,1.2c-1.2,0.8-2.7,1.8-2.7,3.8c0,0.4,0.2,0.9,0.3,1.4c0,0.3,0,0.6,0,0.9'+
+ 'c0.1,0.7,0.6,1.7,0,2.2c-0.9-0.4-1.9-0.5-2.5-1.2c-0.2-0.7,0.3-1.3,0.3-1.9c-0.1-0.5-0.7-1.4-1.1-1.5c-0.4-0.1-0.7,0.4-1.1,0.4'+
+ 'c-0.5,0-0.9-0.8-1.5-0.9c-0.9-0.1-1.6,0.2-2.5,0.1c-1,0.6-1.2,1.6-2.4,1.5c-0.4,0-0.8-0.4-1.3-0.5c-0.5-0.1-1.3-0.3-1.8-0.3'+
+ 'c-1.1,0.1-1.9,1-2.8,1.5c-0.8,0.5-2,1.1-2.2,2.1c-0.1,0.5,0,1.3-0.2,1.8c-0.1,0.3-0.4,0.6-0.5,0.9c-0.7,1.5-1.3,3.4-0.8,5.5'+
+ 'c0.1,0.3,0.8,2.1,1.1,2.4c0.3,0.4,1.3,1,1.8,1c0.5,0,1-0.3,1.5-0.4c0.5-0.1,1.2-0.1,1.7-0.3c1.4-0.5,1.1-2.6,2.5-3.3'+
+ 'c0.6-0.3,1.3-0.4,2.4-0.4c0.3,0.3,0.5,0.9,0.4,1.4c0,0.4-0.3,0.7-0.5,1.2c-0.1,0.5-0.2,1-0.3,1.4c-0.2,0.5-0.6,0.8-0.8,1.3'+
+ 'c-0.1,0.3,0,0.7-0.1,0.9c-0.1,0.5-0.7,0.8-0.4,1.3c1.4,0.6,3-0.2,4.2,0.1c0.5,0.1,1.5,0.8,1.5,1.7c0,0.7-0.4,1.1-0.5,1.8'+
+ 'c-0.1,0.9-0.4,2-0.4,2.7c-0.1,1.2,1.5,3.2,2.7,3.2L55.7,94.6z M39.1,54.2L31.7,54v11.2h10.3v-8.7L39.1,54.2z M52.2,35.7l7.5,0.1'+
+ 'V24.6H49.5l0,8.9 M39.1,54.2l2.9,2.3l10.3-20.8l-2.7-2.1L39.1,54.2z M47.2,46.4'
+
+ }
+ },
+
+ // detail panel button definitions
+ buttons: {
+ src: {
+ gid: '*src',
+ tt: 'Set source node',
+ cb: function (data) {
+ $log.debug('Set src action invoked with data:', data);
+ pps.setSrc(selection);
+ }
+ },
+ dst: {
+ gid: '*dst',
+ tt: 'Set destination node',
+ cb: function (data) {
+ $log.debug('Set dst action invoked with data:', data);
+ pps.setDst(selection);
+ }
+ }
+ },
+
+ // Key bindings for traffic overlay buttons
+ // NOTE: fully qual. button ID is derived from overlay-id and key-name
+ // FIXME: use into [ and ] instead of 1 and 2
+ // FIXME: find better keys for shortest paths & disjoint paths modes
+ keyBindings: {
+ 1: {
+ cb: function () {
+ pps.setSrc(selection);
+ },
+ tt: 'Set source node',
+ gid: '*src'
+ },
+ 2: {
+ cb: function () {
+ pps.setDst(selection);
+ },
+ tt: 'Set destination node',
+ gid: '*dst'
+ },
+ 3: {
+ cb: function () {
+ pps.swapSrcDst();
+ },
+ tt: 'Swap source and destination nodes',
+ gid: 'refresh'
+ },
+ 4: {
+ cb: function () {
+ pps.setMode("shortest");
+ },
+ tt: 'Set shortest paths mode',
+ gid: '*jp'
+ },
+ 5: {
+ cb: function () {
+ pps.setMode("disjoint");
+ },
+ tt: 'Set disjoint paths mode',
+ gid: '*djp'
+ },
+ 6: {
+ cb: function () {
+ pps.setMode("geodata");
+ },
+ tt: 'Set geodata path weight mode',
+ gid: '*geo'
+ },
+ leftArrow: {
+ cb: function () {
+ pps.prevPath();
+ },
+ tt: 'Highlight previous path',
+ gid: 'prevIntent'
+ },
+ rightArrow: {
+ cb: function () {
+ pps.nextPath();
+ },
+ tt: 'Highlight next path',
+ gid: 'nextIntent'
+ },
+
+ _keyOrder: [
+ '1', '2', '3', '4', '5', '6', 'leftArrow', 'rightArrow'
+ ]
+ },
+
+ hooks: {
+ // hook for handling escape key
+ // Must return true to consume ESC, false otherwise.
+ escape: function () {
+ selectionCallback();
+ pps.setSrc();
+ pps.setDst();
+ },
+
+ // hooks for when the selection changes...
+ empty: function () {
+ selectionCallback();
+ },
+ single: function (data) {
+ selectionCallback(data);
+ }
+ }
+ };
+
+
+ function buttonCallback(x) {
+ $log.debug('Toolbar-button callback', x);
+ }
+
+ function selectionCallback(d) {
+ $log.debug('Selection callback', d);
+ selection = d;
+ }
+
+ // invoke code to register with the overlay service
+ angular.module('ovPpTopov')
+ .run(['$log', 'TopoOverlayService', 'PathPainterTopovService',
+
+ function (_$log_, _tov_, _pps_) {
+ $log = _$log_;
+ tov = _tov_;
+ pps = _pps_;
+ tov.register(overlay);
+ }]);
+
+}());
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html
new file mode 100644
index 00000000..56b32b4a
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html
@@ -0,0 +1 @@
+<link rel="stylesheet" href="app/view/ppTopov/ppTopov.css"> \ No newline at end of file
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html
new file mode 100644
index 00000000..24124bf7
--- /dev/null
+++ b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html
@@ -0,0 +1,2 @@
+<script src="app/view/ppTopov/ppTopov.js"></script>
+<script src="app/view/ppTopov/ppTopovOverlay.js"></script> \ No newline at end of file