ONOS-2186 - GUI Topo Overlay - (WIP)
- split BiLink into abstract superclass and concrete subclasses. - created BiLinkMap to collate bilinks (and derivative subclasses). - added missing Javadocs, and other general cleanup. Change-Id: Icfa85bc44a223c6cf245a4005170583dad1cc801
Showing
20 changed files
with
603 additions
and
325 deletions
| ... | @@ -18,22 +18,38 @@ | ... | @@ -18,22 +18,38 @@ |
| 18 | package org.onosproject.ui.topo; | 18 | package org.onosproject.ui.topo; |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | - * Partial implementation of the types of highlight to apply to topology | 21 | + * Partial implementation of the highlighting to apply to topology |
| 22 | - * elements. | 22 | + * view elements. |
| 23 | */ | 23 | */ |
| 24 | public abstract class AbstractHighlight { | 24 | public abstract class AbstractHighlight { |
| 25 | private final TopoElementType type; | 25 | private final TopoElementType type; |
| 26 | private final String elementId; | 26 | private final String elementId; |
| 27 | 27 | ||
| 28 | + /** | ||
| 29 | + * Constructs the highlight. | ||
| 30 | + * | ||
| 31 | + * @param type highlight element type | ||
| 32 | + * @param elementId element identifier | ||
| 33 | + */ | ||
| 28 | public AbstractHighlight(TopoElementType type, String elementId) { | 34 | public AbstractHighlight(TopoElementType type, String elementId) { |
| 29 | this.type = type; | 35 | this.type = type; |
| 30 | this.elementId = elementId; | 36 | this.elementId = elementId; |
| 31 | } | 37 | } |
| 32 | 38 | ||
| 39 | + /** | ||
| 40 | + * Returns the element type. | ||
| 41 | + * | ||
| 42 | + * @return element type | ||
| 43 | + */ | ||
| 33 | public TopoElementType type() { | 44 | public TopoElementType type() { |
| 34 | return type; | 45 | return type; |
| 35 | } | 46 | } |
| 36 | 47 | ||
| 48 | + /** | ||
| 49 | + * Returns the element identifier. | ||
| 50 | + * | ||
| 51 | + * @return element identifier | ||
| 52 | + */ | ||
| 37 | public String elementId() { | 53 | public String elementId() { |
| 38 | return elementId; | 54 | return elementId; |
| 39 | } | 55 | } | ... | ... |
| ... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
| 18 | package org.onosproject.ui.topo; | 18 | package org.onosproject.ui.topo; |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | - * Denotes the types of highlight to apply to a link. | 21 | + * Denotes the highlighting to apply to a device. |
| 22 | */ | 22 | */ |
| 23 | public class DeviceHighlight extends AbstractHighlight { | 23 | public class DeviceHighlight extends AbstractHighlight { |
| 24 | 24 | ||
| ... | @@ -26,5 +26,8 @@ public class DeviceHighlight extends AbstractHighlight { | ... | @@ -26,5 +26,8 @@ public class DeviceHighlight extends AbstractHighlight { |
| 26 | super(TopoElementType.DEVICE, deviceId); | 26 | super(TopoElementType.DEVICE, deviceId); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | + // TODO: implement device highlighting: | ||
| 30 | + // - visual highlight | ||
| 31 | + // - badging | ||
| 29 | 32 | ||
| 30 | } | 33 | } | ... | ... |
| ... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
| 18 | package org.onosproject.ui.topo; | 18 | package org.onosproject.ui.topo; |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | - * Denotes the types of highlight to apply to a link. | 21 | + * Denotes the highlighting to apply to a host. |
| 22 | */ | 22 | */ |
| 23 | public class HostHighlight extends AbstractHighlight { | 23 | public class HostHighlight extends AbstractHighlight { |
| 24 | 24 | ||
| ... | @@ -26,5 +26,8 @@ public class HostHighlight extends AbstractHighlight { | ... | @@ -26,5 +26,8 @@ public class HostHighlight extends AbstractHighlight { |
| 26 | super(TopoElementType.HOST, hostId); | 26 | super(TopoElementType.HOST, hostId); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | + // TODO: implement host highlighting: | ||
| 30 | + // - visual highlight | ||
| 31 | + // - badging | ||
| 29 | 32 | ||
| 30 | } | 33 | } | ... | ... |
| ... | @@ -27,8 +27,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -27,8 +27,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
| 27 | * Denotes the highlighting to be applied to a link. | 27 | * Denotes the highlighting to be applied to a link. |
| 28 | * {@link Flavor} is a closed set of NO-, PRIMARY-, or SECONDARY- highlighting. | 28 | * {@link Flavor} is a closed set of NO-, PRIMARY-, or SECONDARY- highlighting. |
| 29 | * {@link Mod} is an open ended set of additional modifications (CSS classes) | 29 | * {@link Mod} is an open ended set of additional modifications (CSS classes) |
| 30 | - * to apply. Note that {@link #MOD_OPTICAL} and {@link #MOD_ANIMATED} are | 30 | + * that may also be applied. |
| 31 | - * pre-defined mods. | 31 | + * Note that {@link #MOD_OPTICAL} and {@link #MOD_ANIMATED} are pre-defined mods. |
| 32 | * Label text may be set, which will also be displayed on the link. | 32 | * Label text may be set, which will also be displayed on the link. |
| 33 | */ | 33 | */ |
| 34 | public class LinkHighlight extends AbstractHighlight { | 34 | public class LinkHighlight extends AbstractHighlight { |
| ... | @@ -136,48 +136,6 @@ public class LinkHighlight extends AbstractHighlight { | ... | @@ -136,48 +136,6 @@ public class LinkHighlight extends AbstractHighlight { |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | /** | 138 | /** |
| 139 | - * Link highlighting modification. | ||
| 140 | - * <p> | ||
| 141 | - * Note that this translates to a CSS class name that is applied to | ||
| 142 | - * the link in the Topology UI. | ||
| 143 | - */ | ||
| 144 | - public static final class Mod implements Comparable<Mod> { | ||
| 145 | - private final String modId; | ||
| 146 | - | ||
| 147 | - public Mod(String modId) { | ||
| 148 | - this.modId = checkNotNull(modId); | ||
| 149 | - } | ||
| 150 | - | ||
| 151 | - @Override | ||
| 152 | - public String toString() { | ||
| 153 | - return modId; | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - @Override | ||
| 157 | - public boolean equals(Object o) { | ||
| 158 | - if (this == o) { | ||
| 159 | - return true; | ||
| 160 | - } | ||
| 161 | - if (o == null || getClass() != o.getClass()) { | ||
| 162 | - return false; | ||
| 163 | - } | ||
| 164 | - Mod mod = (Mod) o; | ||
| 165 | - return modId.equals(mod.modId); | ||
| 166 | - } | ||
| 167 | - | ||
| 168 | - @Override | ||
| 169 | - public int hashCode() { | ||
| 170 | - return modId.hashCode(); | ||
| 171 | - } | ||
| 172 | - | ||
| 173 | - | ||
| 174 | - @Override | ||
| 175 | - public int compareTo(Mod o) { | ||
| 176 | - return this.modId.compareTo(o.modId); | ||
| 177 | - } | ||
| 178 | - } | ||
| 179 | - | ||
| 180 | - /** | ||
| 181 | * Denotes a link to be tagged as an optical link. | 139 | * Denotes a link to be tagged as an optical link. |
| 182 | */ | 140 | */ |
| 183 | public static final Mod MOD_OPTICAL = new Mod("optical"); | 141 | public static final Mod MOD_OPTICAL = new Mod("optical"); | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + * | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +package org.onosproject.ui.topo; | ||
| 19 | + | ||
| 20 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Highlighting modification. | ||
| 24 | + * <p> | ||
| 25 | + * Note that (for link highlights) this translates to a CSS class name | ||
| 26 | + * that is applied to the link in the Topology UI. | ||
| 27 | + */ | ||
| 28 | +public final class Mod implements Comparable<Mod> { | ||
| 29 | + private final String modId; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Constructs a mod with the given identifier. | ||
| 33 | + * | ||
| 34 | + * @param modId modification identifier | ||
| 35 | + */ | ||
| 36 | + public Mod(String modId) { | ||
| 37 | + this.modId = checkNotNull(modId); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public String toString() { | ||
| 42 | + return modId; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Override | ||
| 46 | + public boolean equals(Object o) { | ||
| 47 | + if (this == o) { | ||
| 48 | + return true; | ||
| 49 | + } | ||
| 50 | + if (o == null || getClass() != o.getClass()) { | ||
| 51 | + return false; | ||
| 52 | + } | ||
| 53 | + Mod mod = (Mod) o; | ||
| 54 | + return modId.equals(mod.modId); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public int hashCode() { | ||
| 59 | + return modId.hashCode(); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @Override | ||
| 63 | + public int compareTo(Mod o) { | ||
| 64 | + return this.modId.compareTo(o.modId); | ||
| 65 | + } | ||
| 66 | +} |
| ... | @@ -18,21 +18,18 @@ package org.onosproject.ui.impl; | ... | @@ -18,21 +18,18 @@ package org.onosproject.ui.impl; |
| 18 | 18 | ||
| 19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 20 | import com.google.common.collect.ImmutableSet; | 20 | import com.google.common.collect.ImmutableSet; |
| 21 | -import com.google.common.collect.Maps; | ||
| 22 | import org.onosproject.net.Link; | 21 | import org.onosproject.net.Link; |
| 23 | -import org.onosproject.net.LinkKey; | ||
| 24 | import org.onosproject.net.link.LinkService; | 22 | import org.onosproject.net.link.LinkService; |
| 25 | import org.onosproject.ui.RequestHandler; | 23 | import org.onosproject.ui.RequestHandler; |
| 26 | import org.onosproject.ui.UiMessageHandler; | 24 | import org.onosproject.ui.UiMessageHandler; |
| 27 | -import org.onosproject.ui.impl.topo.BiLink; | 25 | +import org.onosproject.ui.impl.topo.BaseLink; |
| 28 | -import org.onosproject.ui.impl.topo.TopoUtils; | 26 | +import org.onosproject.ui.impl.topo.BaseLinkMap; |
| 29 | import org.onosproject.ui.table.TableModel; | 27 | import org.onosproject.ui.table.TableModel; |
| 30 | import org.onosproject.ui.table.TableRequestHandler; | 28 | import org.onosproject.ui.table.TableRequestHandler; |
| 31 | import org.onosproject.ui.table.cell.ConnectPointFormatter; | 29 | import org.onosproject.ui.table.cell.ConnectPointFormatter; |
| 32 | import org.onosproject.ui.table.cell.EnumFormatter; | 30 | import org.onosproject.ui.table.cell.EnumFormatter; |
| 33 | 31 | ||
| 34 | import java.util.Collection; | 32 | import java.util.Collection; |
| 35 | -import java.util.Map; | ||
| 36 | 33 | ||
| 37 | /** | 34 | /** |
| 38 | * Message handler for link view related messages. | 35 | * Message handler for link view related messages. |
| ... | @@ -41,6 +38,7 @@ public class LinkViewMessageHandler extends UiMessageHandler { | ... | @@ -41,6 +38,7 @@ public class LinkViewMessageHandler extends UiMessageHandler { |
| 41 | 38 | ||
| 42 | private static final String A_BOTH_B = "A ↔ B"; | 39 | private static final String A_BOTH_B = "A ↔ B"; |
| 43 | private static final String A_SINGLE_B = "A → B"; | 40 | private static final String A_SINGLE_B = "A → B"; |
| 41 | + private static final String SLASH = " / "; | ||
| 44 | 42 | ||
| 45 | private static final String LINK_DATA_REQ = "linkDataRequest"; | 43 | private static final String LINK_DATA_REQ = "linkDataRequest"; |
| 46 | private static final String LINK_DATA_RESP = "linkDataResponse"; | 44 | private static final String LINK_DATA_RESP = "linkDataResponse"; |
| ... | @@ -93,42 +91,37 @@ public class LinkViewMessageHandler extends UiMessageHandler { | ... | @@ -93,42 +91,37 @@ public class LinkViewMessageHandler extends UiMessageHandler { |
| 93 | @Override | 91 | @Override |
| 94 | protected void populateTable(TableModel tm, ObjectNode payload) { | 92 | protected void populateTable(TableModel tm, ObjectNode payload) { |
| 95 | LinkService ls = get(LinkService.class); | 93 | LinkService ls = get(LinkService.class); |
| 96 | - | 94 | + BaseLinkMap linkMap = new BaseLinkMap(); |
| 97 | - // First consolidate all uni-directional links into two-directional ones. | 95 | + ls.getLinks().forEach(linkMap::add); |
| 98 | - Map<LinkKey, BiLink> biLinks = Maps.newHashMap(); | 96 | + linkMap.biLinks().forEach(blink -> populateRow(tm.addRow(), blink)); |
| 99 | - ls.getLinks().forEach(link -> TopoUtils.addLink(biLinks, link)); | ||
| 100 | - | ||
| 101 | - // Now scan over all bi-links and produce table rows from them. | ||
| 102 | - biLinks.values().forEach(biLink -> populateRow(tm.addRow(), biLink)); | ||
| 103 | } | 97 | } |
| 104 | 98 | ||
| 105 | - private void populateRow(TableModel.Row row, BiLink biLink) { | 99 | + private void populateRow(TableModel.Row row, BaseLink blink) { |
| 106 | - row.cell(ONE, biLink.one().src()) | 100 | + row.cell(ONE, blink.one().src()) |
| 107 | - .cell(TWO, biLink.one().dst()) | 101 | + .cell(TWO, blink.one().dst()) |
| 108 | - .cell(TYPE, linkType(biLink)) | 102 | + .cell(TYPE, linkType(blink)) |
| 109 | - .cell(STATE, linkState(biLink)) | 103 | + .cell(STATE, linkState(blink)) |
| 110 | - .cell(DIRECTION, linkDir(biLink)) | 104 | + .cell(DIRECTION, linkDir(blink)) |
| 111 | - .cell(DURABLE, biLink.one().isDurable()); | 105 | + .cell(DURABLE, blink.one().isDurable()); |
| 112 | } | 106 | } |
| 113 | 107 | ||
| 114 | - private String linkType(BiLink link) { | 108 | + private String linkType(BaseLink link) { |
| 115 | StringBuilder sb = new StringBuilder(); | 109 | StringBuilder sb = new StringBuilder(); |
| 116 | sb.append(link.one().type()); | 110 | sb.append(link.one().type()); |
| 117 | if (link.two() != null && link.two().type() != link.one().type()) { | 111 | if (link.two() != null && link.two().type() != link.one().type()) { |
| 118 | - sb.append(" / ").append(link.two().type()); | 112 | + sb.append(SLASH).append(link.two().type()); |
| 119 | } | 113 | } |
| 120 | return sb.toString(); | 114 | return sb.toString(); |
| 121 | } | 115 | } |
| 122 | 116 | ||
| 123 | - private String linkState(BiLink link) { | 117 | + private String linkState(BaseLink link) { |
| 124 | return (link.one().state() == Link.State.ACTIVE || | 118 | return (link.one().state() == Link.State.ACTIVE || |
| 125 | link.two().state() == Link.State.ACTIVE) ? | 119 | link.two().state() == Link.State.ACTIVE) ? |
| 126 | ICON_ID_ONLINE : ICON_ID_OFFLINE; | 120 | ICON_ID_ONLINE : ICON_ID_OFFLINE; |
| 127 | } | 121 | } |
| 128 | 122 | ||
| 129 | - private String linkDir(BiLink link) { | 123 | + private String linkDir(BaseLink link) { |
| 130 | return link.two() != null ? A_BOTH_B : A_SINGLE_B; | 124 | return link.two() != null ? A_BOTH_B : A_SINGLE_B; |
| 131 | } | 125 | } |
| 132 | } | 126 | } |
| 133 | - | ||
| 134 | } | 127 | } | ... | ... |
| ... | @@ -56,7 +56,7 @@ import org.onosproject.net.link.LinkListener; | ... | @@ -56,7 +56,7 @@ import org.onosproject.net.link.LinkListener; |
| 56 | import org.onosproject.ui.JsonUtils; | 56 | import org.onosproject.ui.JsonUtils; |
| 57 | import org.onosproject.ui.RequestHandler; | 57 | import org.onosproject.ui.RequestHandler; |
| 58 | import org.onosproject.ui.UiConnection; | 58 | import org.onosproject.ui.UiConnection; |
| 59 | -import org.onosproject.ui.impl.TrafficMonitorObject.Mode; | 59 | +import org.onosproject.ui.impl.TrafficMonitor.Mode; |
| 60 | import org.onosproject.ui.impl.topo.NodeSelection; | 60 | import org.onosproject.ui.impl.topo.NodeSelection; |
| 61 | import org.onosproject.ui.topo.Highlights; | 61 | import org.onosproject.ui.topo.Highlights; |
| 62 | import org.onosproject.ui.topo.PropertyPanel; | 62 | import org.onosproject.ui.topo.PropertyPanel; |
| ... | @@ -162,9 +162,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -162,9 +162,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 162 | private final ExecutorService msgSender = | 162 | private final ExecutorService msgSender = |
| 163 | newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender")); | 163 | newSingleThreadExecutor(groupedThreads("onos/gui", "msg-sender")); |
| 164 | 164 | ||
| 165 | - private TrafficMonitorObject tmo; | ||
| 166 | - | ||
| 167 | private TopoOverlayCache overlayCache; | 165 | private TopoOverlayCache overlayCache; |
| 166 | + private TrafficMonitor traffic; | ||
| 168 | 167 | ||
| 169 | private TimerTask summaryTask = null; | 168 | private TimerTask summaryTask = null; |
| 170 | private boolean summaryRunning = false; | 169 | private boolean summaryRunning = false; |
| ... | @@ -176,7 +175,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -176,7 +175,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 176 | public void init(UiConnection connection, ServiceDirectory directory) { | 175 | public void init(UiConnection connection, ServiceDirectory directory) { |
| 177 | super.init(connection, directory); | 176 | super.init(connection, directory); |
| 178 | appId = directory.get(CoreService.class).registerApplication(APP_ID); | 177 | appId = directory.get(CoreService.class).registerApplication(APP_ID); |
| 179 | - tmo = new TrafficMonitorObject(TRAFFIC_PERIOD, servicesBundle, this); | 178 | + traffic = new TrafficMonitor(TRAFFIC_PERIOD, servicesBundle, this); |
| 180 | } | 179 | } |
| 181 | 180 | ||
| 182 | @Override | 181 | @Override |
| ... | @@ -275,7 +274,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -275,7 +274,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 275 | @Override | 274 | @Override |
| 276 | public void process(long sid, ObjectNode payload) { | 275 | public void process(long sid, ObjectNode payload) { |
| 277 | stopSummaryMonitoring(); | 276 | stopSummaryMonitoring(); |
| 278 | - tmo.stop(); | 277 | + traffic.stopMonitoring(); |
| 279 | } | 278 | } |
| 280 | } | 279 | } |
| 281 | 280 | ||
| ... | @@ -400,7 +399,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -400,7 +399,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 400 | .build(); | 399 | .build(); |
| 401 | 400 | ||
| 402 | intentService.submit(intent); | 401 | intentService.submit(intent); |
| 403 | - tmo.monitor(intent); | 402 | + traffic.monitor(intent); |
| 404 | } | 403 | } |
| 405 | } | 404 | } |
| 406 | 405 | ||
| ... | @@ -433,7 +432,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -433,7 +432,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 433 | .build(); | 432 | .build(); |
| 434 | 433 | ||
| 435 | intentService.submit(intent); | 434 | intentService.submit(intent); |
| 436 | - tmo.monitor(intent); | 435 | + traffic.monitor(intent); |
| 437 | } | 436 | } |
| 438 | } | 437 | } |
| 439 | 438 | ||
| ... | @@ -446,7 +445,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -446,7 +445,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 446 | 445 | ||
| 447 | @Override | 446 | @Override |
| 448 | public void process(long sid, ObjectNode payload) { | 447 | public void process(long sid, ObjectNode payload) { |
| 449 | - tmo.monitor(Mode.ALL_FLOW_TRAFFIC); | 448 | + traffic.monitor(Mode.ALL_FLOW_TRAFFIC); |
| 450 | } | 449 | } |
| 451 | } | 450 | } |
| 452 | 451 | ||
| ... | @@ -457,7 +456,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -457,7 +456,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 457 | 456 | ||
| 458 | @Override | 457 | @Override |
| 459 | public void process(long sid, ObjectNode payload) { | 458 | public void process(long sid, ObjectNode payload) { |
| 460 | - tmo.monitor(Mode.ALL_PORT_TRAFFIC); | 459 | + traffic.monitor(Mode.ALL_PORT_TRAFFIC); |
| 461 | } | 460 | } |
| 462 | } | 461 | } |
| 463 | 462 | ||
| ... | @@ -470,7 +469,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -470,7 +469,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 470 | public void process(long sid, ObjectNode payload) { | 469 | public void process(long sid, ObjectNode payload) { |
| 471 | NodeSelection nodeSelection = | 470 | NodeSelection nodeSelection = |
| 472 | new NodeSelection(payload, deviceService, hostService); | 471 | new NodeSelection(payload, deviceService, hostService); |
| 473 | - tmo.monitor(Mode.DEV_LINK_FLOWS, nodeSelection); | 472 | + traffic.monitor(Mode.DEV_LINK_FLOWS, nodeSelection); |
| 474 | } | 473 | } |
| 475 | } | 474 | } |
| 476 | 475 | ||
| ... | @@ -483,7 +482,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -483,7 +482,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 483 | public void process(long sid, ObjectNode payload) { | 482 | public void process(long sid, ObjectNode payload) { |
| 484 | NodeSelection nodeSelection = | 483 | NodeSelection nodeSelection = |
| 485 | new NodeSelection(payload, deviceService, hostService); | 484 | new NodeSelection(payload, deviceService, hostService); |
| 486 | - tmo.monitor(Mode.RELATED_INTENTS, nodeSelection); | 485 | + traffic.monitor(Mode.RELATED_INTENTS, nodeSelection); |
| 487 | } | 486 | } |
| 488 | } | 487 | } |
| 489 | 488 | ||
| ... | @@ -494,7 +493,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -494,7 +493,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 494 | 493 | ||
| 495 | @Override | 494 | @Override |
| 496 | public void process(long sid, ObjectNode payload) { | 495 | public void process(long sid, ObjectNode payload) { |
| 497 | - tmo.selectNextIntent(); | 496 | + traffic.selectNextIntent(); |
| 498 | } | 497 | } |
| 499 | } | 498 | } |
| 500 | 499 | ||
| ... | @@ -505,7 +504,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -505,7 +504,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 505 | 504 | ||
| 506 | @Override | 505 | @Override |
| 507 | public void process(long sid, ObjectNode payload) { | 506 | public void process(long sid, ObjectNode payload) { |
| 508 | - tmo.selectPreviousIntent(); | 507 | + traffic.selectPreviousIntent(); |
| 509 | } | 508 | } |
| 510 | } | 509 | } |
| 511 | 510 | ||
| ... | @@ -516,7 +515,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -516,7 +515,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 516 | 515 | ||
| 517 | @Override | 516 | @Override |
| 518 | public void process(long sid, ObjectNode payload) { | 517 | public void process(long sid, ObjectNode payload) { |
| 519 | - tmo.monitor(Mode.SEL_INTENT); | 518 | + traffic.monitor(Mode.SELECTED_INTENT); |
| 520 | } | 519 | } |
| 521 | } | 520 | } |
| 522 | 521 | ||
| ... | @@ -527,7 +526,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -527,7 +526,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 527 | 526 | ||
| 528 | @Override | 527 | @Override |
| 529 | public void process(long sid, ObjectNode payload) { | 528 | public void process(long sid, ObjectNode payload) { |
| 530 | - tmo.stop(); | 529 | + traffic.stopMonitoring(); |
| 531 | } | 530 | } |
| 532 | } | 531 | } |
| 533 | 532 | ||
| ... | @@ -557,7 +556,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -557,7 +556,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 557 | 556 | ||
| 558 | private void cancelAllRequests() { | 557 | private void cancelAllRequests() { |
| 559 | stopSummaryMonitoring(); | 558 | stopSummaryMonitoring(); |
| 560 | - tmo.stop(); | 559 | + traffic.stopMonitoring(); |
| 561 | } | 560 | } |
| 562 | 561 | ||
| 563 | // Sends all controller nodes to the client as node-added messages. | 562 | // Sends all controller nodes to the client as node-added messages. |
| ... | @@ -726,7 +725,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { | ... | @@ -726,7 +725,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { |
| 726 | private class InternalIntentListener implements IntentListener { | 725 | private class InternalIntentListener implements IntentListener { |
| 727 | @Override | 726 | @Override |
| 728 | public void event(IntentEvent event) { | 727 | public void event(IntentEvent event) { |
| 729 | - msgSender.execute(tmo::pokeIntent); | 728 | + msgSender.execute(traffic::pokeIntent); |
| 730 | eventAccummulator.add(event); | 729 | eventAccummulator.add(event); |
| 731 | } | 730 | } |
| 732 | } | 731 | } | ... | ... |
This diff is collapsed. Click to expand it.
| 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.topo; | ||
| 19 | + | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.net.LinkKey; | ||
| 22 | +import org.onosproject.ui.topo.LinkHighlight; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * A simple concrete implementation of a {@link BiLink}. | ||
| 26 | + * Note that this implementation does not generate any link highlights. | ||
| 27 | + */ | ||
| 28 | +public class BaseLink extends BiLink { | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * Constructs a base link for the given key and initial link. | ||
| 32 | + * | ||
| 33 | + * @param key canonical key for this base link | ||
| 34 | + * @param link first link | ||
| 35 | + */ | ||
| 36 | + public BaseLink(LinkKey key, Link link) { | ||
| 37 | + super(key, link); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public LinkHighlight highlight(Enum<?> type) { | ||
| 42 | + return null; | ||
| 43 | + } | ||
| 44 | +} |
| ... | @@ -17,27 +17,15 @@ | ... | @@ -17,27 +17,15 @@ |
| 17 | 17 | ||
| 18 | package org.onosproject.ui.impl.topo; | 18 | package org.onosproject.ui.impl.topo; |
| 19 | 19 | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.net.LinkKey; | ||
| 22 | + | ||
| 20 | /** | 23 | /** |
| 21 | - * Designates type of stats to report on a highlighted link. | 24 | + * Collection of {@link BaseLink}s. |
| 22 | */ | 25 | */ |
| 23 | -public enum LinkStatsType { | 26 | +public class BaseLinkMap extends BiLinkMap<BaseLink> { |
| 24 | - /** | 27 | + @Override |
| 25 | - * Number of flows. | 28 | + public BaseLink create(LinkKey key, Link link) { |
| 26 | - */ | 29 | + return new BaseLink(key, link); |
| 27 | - FLOW_COUNT, | 30 | + } |
| 28 | - | ||
| 29 | - /** | ||
| 30 | - * Number of bytes. | ||
| 31 | - */ | ||
| 32 | - FLOW_STATS, | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * Number of bits per second. | ||
| 36 | - */ | ||
| 37 | - PORT_STATS, | ||
| 38 | - | ||
| 39 | - /** | ||
| 40 | - * Custom tagged information. | ||
| 41 | - */ | ||
| 42 | - TAGGED | ||
| 43 | } | 31 | } | ... | ... |
| ... | @@ -19,226 +19,87 @@ package org.onosproject.ui.impl.topo; | ... | @@ -19,226 +19,87 @@ package org.onosproject.ui.impl.topo; |
| 19 | 19 | ||
| 20 | import org.onosproject.net.Link; | 20 | import org.onosproject.net.Link; |
| 21 | import org.onosproject.net.LinkKey; | 21 | import org.onosproject.net.LinkKey; |
| 22 | -import org.onosproject.net.statistic.Load; | ||
| 23 | import org.onosproject.ui.topo.LinkHighlight; | 22 | import org.onosproject.ui.topo.LinkHighlight; |
| 24 | 23 | ||
| 25 | -import static org.onosproject.ui.topo.LinkHighlight.Flavor.NO_HIGHLIGHT; | 24 | +import static com.google.common.base.Preconditions.checkNotNull; |
| 26 | -import static org.onosproject.ui.topo.LinkHighlight.Flavor.PRIMARY_HIGHLIGHT; | ||
| 27 | -import static org.onosproject.ui.topo.LinkHighlight.Flavor.SECONDARY_HIGHLIGHT; | ||
| 28 | 25 | ||
| 29 | /** | 26 | /** |
| 30 | - * Representation of a link and its inverse, and any associated traffic data. | 27 | + * Representation of a link and its inverse, as a partial implementation. |
| 31 | - * This class understands how to generate {@link LinkHighlight}s for sending | 28 | + * <p> |
| 32 | - * back to the topology view. | 29 | + * Subclasses will decide how to generate the link highlighting (coloring |
| 30 | + * and labeling) for the topology view. | ||
| 33 | */ | 31 | */ |
| 34 | -public class BiLink { | 32 | +public abstract class BiLink { |
| 35 | - | ||
| 36 | - private static final String EMPTY = ""; | ||
| 37 | 33 | ||
| 38 | private final LinkKey key; | 34 | private final LinkKey key; |
| 39 | private final Link one; | 35 | private final Link one; |
| 40 | private Link two; | 36 | private Link two; |
| 41 | 37 | ||
| 42 | - private boolean hasTraffic = false; | ||
| 43 | - private long bytes = 0; | ||
| 44 | - private long rate = 0; | ||
| 45 | - private long flows = 0; | ||
| 46 | - private boolean isOptical = false; | ||
| 47 | - private LinkHighlight.Flavor taggedFlavor = NO_HIGHLIGHT; | ||
| 48 | - private boolean antMarch = false; | ||
| 49 | - | ||
| 50 | /** | 38 | /** |
| 51 | - * Constructs a bilink for the given key and initial link. | 39 | + * Constructs a bi-link for the given key and initial link. It is expected |
| 40 | + * that the caller will have used {@link TopoUtils#canonicalLinkKey(Link)} | ||
| 41 | + * to generate the key. | ||
| 52 | * | 42 | * |
| 53 | - * @param key canonical key for this bilink | 43 | + * @param key canonical key for this bi-link |
| 54 | * @param link first link | 44 | * @param link first link |
| 55 | */ | 45 | */ |
| 56 | public BiLink(LinkKey key, Link link) { | 46 | public BiLink(LinkKey key, Link link) { |
| 57 | - this.key = key; | 47 | + this.key = checkNotNull(key); |
| 58 | - this.one = link; | 48 | + this.one = checkNotNull(link); |
| 59 | } | 49 | } |
| 60 | 50 | ||
| 61 | /** | 51 | /** |
| 62 | - * Sets the second link for this bilink. | 52 | + * Sets the second link for this bi-link. |
| 63 | * | 53 | * |
| 64 | * @param link second link | 54 | * @param link second link |
| 65 | */ | 55 | */ |
| 66 | public void setOther(Link link) { | 56 | public void setOther(Link link) { |
| 67 | - this.two = link; | 57 | + this.two = checkNotNull(link); |
| 68 | } | 58 | } |
| 69 | 59 | ||
| 70 | /** | 60 | /** |
| 71 | - * Sets the optical flag to the given value. | 61 | + * Returns the link identifier in the form expected on the Topology View |
| 62 | + * in the web client. | ||
| 72 | * | 63 | * |
| 73 | - * @param b true if an optical link | 64 | + * @return link identifier |
| 74 | */ | 65 | */ |
| 75 | - public void setOptical(boolean b) { | 66 | + public String linkId() { |
| 76 | - isOptical = b; | 67 | + return TopoUtils.compactLinkString(one); |
| 77 | - } | ||
| 78 | - | ||
| 79 | - /** | ||
| 80 | - * Sets the ant march flag to the given value. | ||
| 81 | - * | ||
| 82 | - * @param b true if marching ants required | ||
| 83 | - */ | ||
| 84 | - public void setAntMarch(boolean b) { | ||
| 85 | - antMarch = b; | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | - /** | ||
| 89 | - * Tags this bilink with a link flavor to be used in visual rendering. | ||
| 90 | - * | ||
| 91 | - * @param flavor the flavor to tag | ||
| 92 | - */ | ||
| 93 | - public void tagFlavor(LinkHighlight.Flavor flavor) { | ||
| 94 | - this.taggedFlavor = flavor; | ||
| 95 | } | 68 | } |
| 96 | 69 | ||
| 97 | /** | 70 | /** |
| 98 | - * Adds load statistics, marks the bilink as having traffic. | 71 | + * Returns the key for this bi-link. |
| 99 | * | 72 | * |
| 100 | - * @param load load to add | 73 | + * @return the key |
| 101 | */ | 74 | */ |
| 102 | - public void addLoad(Load load) { | 75 | + public LinkKey key() { |
| 103 | - addLoad(load, 0); | 76 | + return key; |
| 104 | } | 77 | } |
| 105 | 78 | ||
| 106 | /** | 79 | /** |
| 107 | - * Adds load statistics, marks the bilink as having traffic, if the | 80 | + * Returns the first link in this bi-link. |
| 108 | - * load rate is greater than the given threshold. | ||
| 109 | * | 81 | * |
| 110 | - * @param load load to add | 82 | + * @return the first link |
| 111 | - * @param threshold threshold to register traffic | ||
| 112 | */ | 83 | */ |
| 113 | - public void addLoad(Load load, double threshold) { | 84 | + public Link one() { |
| 114 | - if (load != null) { | 85 | + return one; |
| 115 | - this.hasTraffic = hasTraffic || load.rate() > threshold; | ||
| 116 | - this.bytes += load.latest(); | ||
| 117 | - this.rate += load.rate(); | ||
| 118 | - } | ||
| 119 | } | 86 | } |
| 120 | 87 | ||
| 121 | /** | 88 | /** |
| 122 | - * Adds the given count of flows to this bilink. | 89 | + * Returns the second link in this bi-link. |
| 123 | * | 90 | * |
| 124 | - * @param count count of flows | 91 | + * @return the second link |
| 125 | */ | 92 | */ |
| 126 | - public void addFlows(int count) { | 93 | + public Link two() { |
| 127 | - this.flows += count; | 94 | + return two; |
| 128 | } | 95 | } |
| 129 | 96 | ||
| 130 | /** | 97 | /** |
| 131 | - * Generates a link highlight entity, based on state of this bilink. | 98 | + * Returns the link highlighting to use, based on this bi-link's current |
| 99 | + * state. | ||
| 132 | * | 100 | * |
| 133 | - * @param type the type of statistics to use to interpret the data | 101 | + * @param type optional highlighting type parameter |
| 134 | - * @return link highlight data for this bilink | 102 | + * @return link highlighting model |
| 135 | */ | 103 | */ |
| 136 | - public LinkHighlight generateHighlight(LinkStatsType type) { | 104 | + public abstract LinkHighlight highlight(Enum<?> type); |
| 137 | - switch (type) { | ||
| 138 | - case FLOW_COUNT: | ||
| 139 | - return highlightForFlowCount(type); | ||
| 140 | - | ||
| 141 | - case FLOW_STATS: | ||
| 142 | - case PORT_STATS: | ||
| 143 | - return highlightForStats(type); | ||
| 144 | - | ||
| 145 | - case TAGGED: | ||
| 146 | - return highlightForTagging(type); | ||
| 147 | - | ||
| 148 | - default: | ||
| 149 | - throw new IllegalStateException("unexpected case: " + type); | ||
| 150 | - } | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - private LinkHighlight highlightForStats(LinkStatsType type) { | ||
| 154 | - return new LinkHighlight(linkId(), SECONDARY_HIGHLIGHT) | ||
| 155 | - .setLabel(generateLabel(type)); | ||
| 156 | - } | ||
| 157 | - | ||
| 158 | - private LinkHighlight highlightForFlowCount(LinkStatsType type) { | ||
| 159 | - LinkHighlight.Flavor flavor = flows() > 0 ? | ||
| 160 | - PRIMARY_HIGHLIGHT : SECONDARY_HIGHLIGHT; | ||
| 161 | - return new LinkHighlight(linkId(), flavor) | ||
| 162 | - .setLabel(generateLabel(type)); | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - private LinkHighlight highlightForTagging(LinkStatsType type) { | ||
| 166 | - LinkHighlight hlite = new LinkHighlight(linkId(), flavor()) | ||
| 167 | - .setLabel(generateLabel(type)); | ||
| 168 | - if (isOptical()) { | ||
| 169 | - hlite.addMod(LinkHighlight.MOD_OPTICAL); | ||
| 170 | - } | ||
| 171 | - if (isAntMarch()) { | ||
| 172 | - hlite.addMod(LinkHighlight.MOD_ANIMATED); | ||
| 173 | - } | ||
| 174 | - return hlite; | ||
| 175 | - } | ||
| 176 | - | ||
| 177 | - // Generates a link identifier in the form that the Topology View on the | ||
| 178 | - private String linkId() { | ||
| 179 | - return TopoUtils.compactLinkString(one); | ||
| 180 | - } | ||
| 181 | - | ||
| 182 | - // Generates a string representation of the load, to be used as a label | ||
| 183 | - private String generateLabel(LinkStatsType type) { | ||
| 184 | - switch (type) { | ||
| 185 | - case FLOW_COUNT: | ||
| 186 | - return TopoUtils.formatFlows(flows()); | ||
| 187 | - | ||
| 188 | - case FLOW_STATS: | ||
| 189 | - return TopoUtils.formatBytes(bytes()); | ||
| 190 | - | ||
| 191 | - case PORT_STATS: | ||
| 192 | - return TopoUtils.formatBitRate(rate()); | ||
| 193 | - | ||
| 194 | - case TAGGED: | ||
| 195 | - return hasTraffic() ? TopoUtils.formatBytes(bytes()) : EMPTY; | ||
| 196 | - | ||
| 197 | - default: | ||
| 198 | - return "?"; | ||
| 199 | - } | ||
| 200 | - } | ||
| 201 | - | ||
| 202 | - // === ---------------------------------------------------------------- | ||
| 203 | - // accessors | ||
| 204 | - | ||
| 205 | - public LinkKey key() { | ||
| 206 | - return key; | ||
| 207 | - } | ||
| 208 | - | ||
| 209 | - public Link one() { | ||
| 210 | - return one; | ||
| 211 | - } | ||
| 212 | - | ||
| 213 | - public Link two() { | ||
| 214 | - return two; | ||
| 215 | - } | ||
| 216 | - | ||
| 217 | - public boolean hasTraffic() { | ||
| 218 | - return hasTraffic; | ||
| 219 | - } | ||
| 220 | - | ||
| 221 | - public boolean isOptical() { | ||
| 222 | - return isOptical; | ||
| 223 | - } | ||
| 224 | - | ||
| 225 | - public boolean isAntMarch() { | ||
| 226 | - return antMarch; | ||
| 227 | - } | ||
| 228 | - | ||
| 229 | - public LinkHighlight.Flavor flavor() { | ||
| 230 | - return taggedFlavor; | ||
| 231 | - } | ||
| 232 | - | ||
| 233 | - public long bytes() { | ||
| 234 | - return bytes; | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | - public long rate() { | ||
| 238 | - return rate; | ||
| 239 | - } | ||
| 240 | - | ||
| 241 | - public long flows() { | ||
| 242 | - return flows; | ||
| 243 | - } | ||
| 244 | } | 105 | } | ... | ... |
| 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.topo; | ||
| 19 | + | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.net.LinkKey; | ||
| 22 | + | ||
| 23 | +import java.util.Collection; | ||
| 24 | +import java.util.HashMap; | ||
| 25 | +import java.util.Map; | ||
| 26 | + | ||
| 27 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 28 | + | ||
| 29 | +/** | ||
| 30 | + * Represents a collection of {@link BiLink} concrete classes. These maps | ||
| 31 | + * are used to collate a set of unidirectional {@link Link}s into a smaller | ||
| 32 | + * set of bi-directional {@link BiLink} derivatives. | ||
| 33 | + * <p> | ||
| 34 | + * @param <B> the type of bi-link subclass | ||
| 35 | + */ | ||
| 36 | +public abstract class BiLinkMap<B extends BiLink> { | ||
| 37 | + | ||
| 38 | + private final Map<LinkKey, B> map = new HashMap<>(); | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * Creates a new instance of a bi-link. Concrete subclasses should | ||
| 42 | + * instantiate and return the appropriate bi-link subclass. | ||
| 43 | + * | ||
| 44 | + * @param key the link key | ||
| 45 | + * @param link the initial link | ||
| 46 | + * @return a new instance | ||
| 47 | + */ | ||
| 48 | + public abstract B create(LinkKey key, Link link); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Adds the given link to our collection, returning the corresponding | ||
| 52 | + * bi-link (creating one if needed necessary). | ||
| 53 | + * | ||
| 54 | + * @param link the link to add to the collection | ||
| 55 | + * @return the corresponding bi-link wrapper | ||
| 56 | + */ | ||
| 57 | + public B add(Link link) { | ||
| 58 | + LinkKey key = TopoUtils.canonicalLinkKey(checkNotNull(link)); | ||
| 59 | + B blink = map.get(key); | ||
| 60 | + if (blink == null) { | ||
| 61 | + // no bi-link yet exists for this link | ||
| 62 | + blink = create(key, link); | ||
| 63 | + map.put(key, blink); | ||
| 64 | + } else { | ||
| 65 | + // we have a bi-link for this link. | ||
| 66 | + if (!blink.one().equals(link)) { | ||
| 67 | + blink.setOther(link); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + return blink; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Returns the bi-link instances in the collection. | ||
| 75 | + * | ||
| 76 | + * @return the bi-links in this map | ||
| 77 | + */ | ||
| 78 | + public Collection<B> biLinks() { | ||
| 79 | + return map.values(); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * Returns the number of bi-links in the collection. | ||
| 84 | + * | ||
| 85 | + * @return number of bi-links | ||
| 86 | + */ | ||
| 87 | + public int size() { | ||
| 88 | + return map.size(); | ||
| 89 | + } | ||
| 90 | +} |
| ... | @@ -47,7 +47,7 @@ public class IntentSelection { | ... | @@ -47,7 +47,7 @@ public class IntentSelection { |
| 47 | * @param nodes node selection | 47 | * @param nodes node selection |
| 48 | * @param filter intent filter | 48 | * @param filter intent filter |
| 49 | */ | 49 | */ |
| 50 | - public IntentSelection(NodeSelection nodes, TopologyViewIntentFilter filter) { | 50 | + public IntentSelection(NodeSelection nodes, TopoIntentFilter filter) { |
| 51 | this.nodes = nodes; | 51 | this.nodes = nodes; |
| 52 | intents = filter.findPathIntents(nodes.hosts(), nodes.devices()); | 52 | intents = filter.findPathIntents(nodes.hosts(), nodes.devices()); |
| 53 | } | 53 | } | ... | ... |
| ... | @@ -41,7 +41,7 @@ import static org.onosproject.net.HostId.hostId; | ... | @@ -41,7 +41,7 @@ import static org.onosproject.net.HostId.hostId; |
| 41 | */ | 41 | */ |
| 42 | public class NodeSelection { | 42 | public class NodeSelection { |
| 43 | 43 | ||
| 44 | - protected static final Logger log = | 44 | + private static final Logger log = |
| 45 | LoggerFactory.getLogger(NodeSelection.class); | 45 | LoggerFactory.getLogger(NodeSelection.class); |
| 46 | 46 | ||
| 47 | private static final String IDS = "ids"; | 47 | private static final String IDS = "ids"; |
| ... | @@ -183,5 +183,4 @@ public class NodeSelection { | ... | @@ -183,5 +183,4 @@ public class NodeSelection { |
| 183 | } | 183 | } |
| 184 | return unmatched; | 184 | return unmatched; |
| 185 | } | 185 | } |
| 186 | - | ||
| 187 | } | 186 | } | ... | ... |
| ... | @@ -42,6 +42,7 @@ public class ServicesBundle { | ... | @@ -42,6 +42,7 @@ public class ServicesBundle { |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Creates the services bundle. | 44 | * Creates the services bundle. |
| 45 | + * | ||
| 45 | * @param intentService intent service reference | 46 | * @param intentService intent service reference |
| 46 | * @param deviceService device service reference | 47 | * @param deviceService device service reference |
| 47 | * @param hostService host service reference | 48 | * @param hostService host service reference |
| ... | @@ -66,30 +67,65 @@ public class ServicesBundle { | ... | @@ -66,30 +67,65 @@ public class ServicesBundle { |
| 66 | this.portStatsService = checkNotNull(portStatsService); | 67 | this.portStatsService = checkNotNull(portStatsService); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 70 | + /** | ||
| 71 | + * Returns a reference to the intent service. | ||
| 72 | + * | ||
| 73 | + * @return intent service reference | ||
| 74 | + */ | ||
| 69 | public IntentService intentService() { | 75 | public IntentService intentService() { |
| 70 | return intentService; | 76 | return intentService; |
| 71 | } | 77 | } |
| 72 | 78 | ||
| 79 | + /** | ||
| 80 | + * Returns a reference to the device service. | ||
| 81 | + * | ||
| 82 | + * @return device service reference | ||
| 83 | + */ | ||
| 73 | public DeviceService deviceService() { | 84 | public DeviceService deviceService() { |
| 74 | return deviceService; | 85 | return deviceService; |
| 75 | } | 86 | } |
| 76 | 87 | ||
| 88 | + /** | ||
| 89 | + * Returns a reference to the host service. | ||
| 90 | + * | ||
| 91 | + * @return host service reference | ||
| 92 | + */ | ||
| 77 | public HostService hostService() { | 93 | public HostService hostService() { |
| 78 | return hostService; | 94 | return hostService; |
| 79 | } | 95 | } |
| 80 | 96 | ||
| 97 | + /** | ||
| 98 | + * Returns a reference to the link service. | ||
| 99 | + * | ||
| 100 | + * @return link service reference | ||
| 101 | + */ | ||
| 81 | public LinkService linkService() { | 102 | public LinkService linkService() { |
| 82 | return linkService; | 103 | return linkService; |
| 83 | } | 104 | } |
| 84 | 105 | ||
| 106 | + /** | ||
| 107 | + * Returns a reference to the flow rule service. | ||
| 108 | + * | ||
| 109 | + * @return flow service reference | ||
| 110 | + */ | ||
| 85 | public FlowRuleService flowService() { | 111 | public FlowRuleService flowService() { |
| 86 | return flowService; | 112 | return flowService; |
| 87 | } | 113 | } |
| 88 | 114 | ||
| 115 | + /** | ||
| 116 | + * Returns a reference to the flow statistics service. | ||
| 117 | + * | ||
| 118 | + * @return flow statistics service reference | ||
| 119 | + */ | ||
| 89 | public StatisticService flowStatsService() { | 120 | public StatisticService flowStatsService() { |
| 90 | return flowStatsService; | 121 | return flowStatsService; |
| 91 | } | 122 | } |
| 92 | 123 | ||
| 124 | + /** | ||
| 125 | + * Returns a reference to the port statistics service. | ||
| 126 | + * | ||
| 127 | + * @return port statistics service reference | ||
| 128 | + */ | ||
| 93 | public PortStatisticsService portStatsService() { | 129 | public PortStatisticsService portStatsService() { |
| 94 | return portStatsService; | 130 | return portStatsService; |
| 95 | } | 131 | } | ... | ... |
| ... | @@ -48,7 +48,7 @@ import static org.onosproject.net.intent.IntentState.INSTALLED; | ... | @@ -48,7 +48,7 @@ import static org.onosproject.net.intent.IntentState.INSTALLED; |
| 48 | * Auxiliary facility to query the intent service based on the specified | 48 | * Auxiliary facility to query the intent service based on the specified |
| 49 | * set of end-station hosts, edge points or infrastructure devices. | 49 | * set of end-station hosts, edge points or infrastructure devices. |
| 50 | */ | 50 | */ |
| 51 | -public class TopologyViewIntentFilter { | 51 | +public class TopoIntentFilter { |
| 52 | 52 | ||
| 53 | private final IntentService intentService; | 53 | private final IntentService intentService; |
| 54 | private final DeviceService deviceService; | 54 | private final DeviceService deviceService; |
| ... | @@ -60,19 +60,13 @@ public class TopologyViewIntentFilter { | ... | @@ -60,19 +60,13 @@ public class TopologyViewIntentFilter { |
| 60 | * | 60 | * |
| 61 | * @param services service references bundle | 61 | * @param services service references bundle |
| 62 | */ | 62 | */ |
| 63 | - public TopologyViewIntentFilter(ServicesBundle services) { | 63 | + public TopoIntentFilter(ServicesBundle services) { |
| 64 | this.intentService = services.intentService(); | 64 | this.intentService = services.intentService(); |
| 65 | this.deviceService = services.deviceService(); | 65 | this.deviceService = services.deviceService(); |
| 66 | this.hostService = services.hostService(); | 66 | this.hostService = services.hostService(); |
| 67 | this.linkService = services.linkService(); | 67 | this.linkService = services.linkService(); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | - | ||
| 71 | - // TODO: Review - do we need this signature, with sourceIntents?? | ||
| 72 | -// public List<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices, | ||
| 73 | -// Iterable<Intent> sourceIntents) { | ||
| 74 | -// } | ||
| 75 | - | ||
| 76 | /** | 70 | /** |
| 77 | * Finds all path (host-to-host or point-to-point) intents that pertain | 71 | * Finds all path (host-to-host or point-to-point) intents that pertain |
| 78 | * to the given hosts and devices. | 72 | * to the given hosts and devices. |
| ... | @@ -277,5 +271,4 @@ public class TopologyViewIntentFilter { | ... | @@ -277,5 +271,4 @@ public class TopologyViewIntentFilter { |
| 277 | } | 271 | } |
| 278 | return null; | 272 | return null; |
| 279 | } | 273 | } |
| 280 | - | ||
| 281 | } | 274 | } | ... | ... |
| ... | @@ -21,15 +21,16 @@ import org.onosproject.net.Link; | ... | @@ -21,15 +21,16 @@ import org.onosproject.net.Link; |
| 21 | import org.onosproject.net.LinkKey; | 21 | import org.onosproject.net.LinkKey; |
| 22 | 22 | ||
| 23 | import java.text.DecimalFormat; | 23 | import java.text.DecimalFormat; |
| 24 | -import java.util.Map; | ||
| 25 | 24 | ||
| 26 | import static org.onosproject.net.LinkKey.linkKey; | 25 | import static org.onosproject.net.LinkKey.linkKey; |
| 27 | 26 | ||
| 28 | /** | 27 | /** |
| 29 | - * Utility methods for helping out with the topology view. | 28 | + * Utility methods for helping out with formatting data for the Topology View |
| 29 | + * in the web client. | ||
| 30 | */ | 30 | */ |
| 31 | public final class TopoUtils { | 31 | public final class TopoUtils { |
| 32 | 32 | ||
| 33 | + // explicit decision made to not 'javadoc' these self explanatory constants | ||
| 33 | public static final double KILO = 1024; | 34 | public static final double KILO = 1024; |
| 34 | public static final double MEGA = 1024 * KILO; | 35 | public static final double MEGA = 1024 * KILO; |
| 35 | public static final double GIGA = 1024 * MEGA; | 36 | public static final double GIGA = 1024 * MEGA; |
| ... | @@ -155,30 +156,4 @@ public final class TopoUtils { | ... | @@ -155,30 +156,4 @@ public final class TopoUtils { |
| 155 | } | 156 | } |
| 156 | return String.valueOf(flows) + SPACE + (flows > 1 ? FLOWS : FLOW); | 157 | return String.valueOf(flows) + SPACE + (flows > 1 ? FLOWS : FLOW); |
| 157 | } | 158 | } |
| 158 | - | ||
| 159 | - | ||
| 160 | - /** | ||
| 161 | - * Creates a new biLink with the supplied link (and adds it to the map), | ||
| 162 | - * or attaches the link to an existing biLink (which already has the | ||
| 163 | - * peer link). | ||
| 164 | - * | ||
| 165 | - * @param linkMap map of biLinks | ||
| 166 | - * @param link the link to add | ||
| 167 | - * @return the biLink to which the link was added | ||
| 168 | - */ | ||
| 169 | - // creates a new biLink with supplied link, or attaches link to the | ||
| 170 | - // existing biLink (which already has its peer link) | ||
| 171 | - public static BiLink addLink(Map<LinkKey, BiLink> linkMap, Link link) { | ||
| 172 | - LinkKey key = TopoUtils.canonicalLinkKey(link); | ||
| 173 | - BiLink biLink = linkMap.get(key); | ||
| 174 | - if (biLink != null) { | ||
| 175 | - biLink.setOther(link); | ||
| 176 | - } else { | ||
| 177 | - biLink = new BiLink(key, link); | ||
| 178 | - linkMap.put(key, biLink); | ||
| 179 | - } | ||
| 180 | - return biLink; | ||
| 181 | - } | ||
| 182 | - | ||
| 183 | - | ||
| 184 | } | 159 | } | ... | ... |
| ... | @@ -24,6 +24,7 @@ import org.onosproject.ui.topo.LinkHighlight; | ... | @@ -24,6 +24,7 @@ import org.onosproject.ui.topo.LinkHighlight; |
| 24 | * Auxiliary data carrier for assigning a highlight class to a set of | 24 | * Auxiliary data carrier for assigning a highlight class to a set of |
| 25 | * intents, for visualization in the topology view. | 25 | * intents, for visualization in the topology view. |
| 26 | */ | 26 | */ |
| 27 | +@Deprecated | ||
| 27 | public class TrafficClass { | 28 | public class TrafficClass { |
| 28 | 29 | ||
| 29 | private final LinkHighlight.Flavor flavor; | 30 | private final LinkHighlight.Flavor flavor; | ... | ... |
| 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.topo; | ||
| 19 | + | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.net.LinkKey; | ||
| 22 | +import org.onosproject.net.statistic.Load; | ||
| 23 | +import org.onosproject.ui.topo.LinkHighlight; | ||
| 24 | +import org.onosproject.ui.topo.LinkHighlight.Flavor; | ||
| 25 | + | ||
| 26 | +import static org.onosproject.ui.topo.LinkHighlight.Flavor.NO_HIGHLIGHT; | ||
| 27 | +import static org.onosproject.ui.topo.LinkHighlight.Flavor.PRIMARY_HIGHLIGHT; | ||
| 28 | +import static org.onosproject.ui.topo.LinkHighlight.Flavor.SECONDARY_HIGHLIGHT; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * Representation of a link and its inverse, and associated traffic data. | ||
| 32 | + * This class understands how to generate the appropriate | ||
| 33 | + * {@link LinkHighlight}s for showing traffic data on the topology view. | ||
| 34 | + */ | ||
| 35 | +public class TrafficLink extends BiLink { | ||
| 36 | + | ||
| 37 | + private static final String EMPTY = ""; | ||
| 38 | + private static final String QUE = "?"; | ||
| 39 | + | ||
| 40 | + private long bytes = 0; | ||
| 41 | + private long rate = 0; | ||
| 42 | + private long flows = 0; | ||
| 43 | + private Flavor taggedFlavor = NO_HIGHLIGHT; | ||
| 44 | + private boolean hasTraffic = false; | ||
| 45 | + private boolean isOptical = false; | ||
| 46 | + private boolean antMarch = false; | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * Constructs a traffic link for the given key and initial link. | ||
| 50 | + * | ||
| 51 | + * @param key canonical key for this traffic link | ||
| 52 | + * @param link first link | ||
| 53 | + */ | ||
| 54 | + public TrafficLink(LinkKey key, Link link) { | ||
| 55 | + super(key, link); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * Sets the optical flag to the given value. | ||
| 60 | + * | ||
| 61 | + * @param b true if an optical link | ||
| 62 | + * @return self, for chaining | ||
| 63 | + */ | ||
| 64 | + public TrafficLink optical(boolean b) { | ||
| 65 | + isOptical = b; | ||
| 66 | + return this; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * Sets the ant march flag to the given value. | ||
| 71 | + * | ||
| 72 | + * @param b true if marching ants required | ||
| 73 | + * @return self, for chaining | ||
| 74 | + */ | ||
| 75 | + public TrafficLink antMarch(boolean b) { | ||
| 76 | + antMarch = b; | ||
| 77 | + return this; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * Tags this traffic link with the flavor to be used in visual rendering. | ||
| 82 | + * | ||
| 83 | + * @param flavor the flavor to tag | ||
| 84 | + * @return self, for chaining | ||
| 85 | + */ | ||
| 86 | + public TrafficLink tagFlavor(Flavor flavor) { | ||
| 87 | + this.taggedFlavor = flavor; | ||
| 88 | + return this; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * Adds load statistics, marks the traffic link as having traffic. | ||
| 93 | + * | ||
| 94 | + * @param load load to add | ||
| 95 | + */ | ||
| 96 | + public void addLoad(Load load) { | ||
| 97 | + addLoad(load, 0); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * Adds load statistics, marks the traffic link as having traffic, if the | ||
| 102 | + * load {@link Load#rate rate} is greater than the given threshold | ||
| 103 | + * (expressed in bytes per second). | ||
| 104 | + * | ||
| 105 | + * @param load load to add | ||
| 106 | + * @param threshold threshold to register traffic | ||
| 107 | + */ | ||
| 108 | + public void addLoad(Load load, double threshold) { | ||
| 109 | + if (load != null) { | ||
| 110 | + this.hasTraffic = hasTraffic || load.rate() > threshold; | ||
| 111 | + this.bytes += load.latest(); | ||
| 112 | + this.rate += load.rate(); | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * Adds the given count of flows to this traffic link. | ||
| 118 | + * | ||
| 119 | + * @param count count of flows | ||
| 120 | + */ | ||
| 121 | + public void addFlows(int count) { | ||
| 122 | + this.flows += count; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + @Override | ||
| 126 | + public LinkHighlight highlight(Enum<?> type) { | ||
| 127 | + StatsType statsType = (StatsType) type; | ||
| 128 | + switch (statsType) { | ||
| 129 | + case FLOW_COUNT: | ||
| 130 | + return highlightForFlowCount(statsType); | ||
| 131 | + | ||
| 132 | + case FLOW_STATS: | ||
| 133 | + case PORT_STATS: | ||
| 134 | + return highlightForStats(statsType); | ||
| 135 | + | ||
| 136 | + case TAGGED: | ||
| 137 | + return highlightForTagging(statsType); | ||
| 138 | + | ||
| 139 | + default: | ||
| 140 | + throw new IllegalStateException("unexpected case: " + statsType); | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + private LinkHighlight highlightForStats(StatsType type) { | ||
| 145 | + return new LinkHighlight(linkId(), SECONDARY_HIGHLIGHT) | ||
| 146 | + .setLabel(generateLabel(type)); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + private LinkHighlight highlightForFlowCount(StatsType type) { | ||
| 150 | + Flavor flavor = flows > 0 ? PRIMARY_HIGHLIGHT : SECONDARY_HIGHLIGHT; | ||
| 151 | + return new LinkHighlight(linkId(), flavor) | ||
| 152 | + .setLabel(generateLabel(type)); | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + private LinkHighlight highlightForTagging(StatsType type) { | ||
| 156 | + LinkHighlight hlite = new LinkHighlight(linkId(), taggedFlavor) | ||
| 157 | + .setLabel(generateLabel(type)); | ||
| 158 | + if (isOptical) { | ||
| 159 | + hlite.addMod(LinkHighlight.MOD_OPTICAL); | ||
| 160 | + } | ||
| 161 | + if (antMarch) { | ||
| 162 | + hlite.addMod(LinkHighlight.MOD_ANIMATED); | ||
| 163 | + } | ||
| 164 | + return hlite; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + // Generates a string representation of the load, to be used as a label | ||
| 168 | + private String generateLabel(StatsType type) { | ||
| 169 | + switch (type) { | ||
| 170 | + case FLOW_COUNT: | ||
| 171 | + return TopoUtils.formatFlows(flows); | ||
| 172 | + | ||
| 173 | + case FLOW_STATS: | ||
| 174 | + return TopoUtils.formatBytes(bytes); | ||
| 175 | + | ||
| 176 | + case PORT_STATS: | ||
| 177 | + return TopoUtils.formatBitRate(rate); | ||
| 178 | + | ||
| 179 | + case TAGGED: | ||
| 180 | + return hasTraffic ? TopoUtils.formatBytes(bytes) : EMPTY; | ||
| 181 | + | ||
| 182 | + default: | ||
| 183 | + return QUE; | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + /** | ||
| 188 | + * Returns true if this link has been deemed to have enough traffic | ||
| 189 | + * to register on the topology view in the web UI. | ||
| 190 | + * | ||
| 191 | + * @return true if this link has displayable traffic | ||
| 192 | + */ | ||
| 193 | + public boolean hasTraffic() { | ||
| 194 | + return hasTraffic; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + /** | ||
| 198 | + * Designates type of traffic statistics to report on a highlighted link. | ||
| 199 | + */ | ||
| 200 | + public enum StatsType { | ||
| 201 | + /** | ||
| 202 | + * Number of flows. | ||
| 203 | + */ | ||
| 204 | + FLOW_COUNT, | ||
| 205 | + | ||
| 206 | + /** | ||
| 207 | + * Number of bytes. | ||
| 208 | + */ | ||
| 209 | + FLOW_STATS, | ||
| 210 | + | ||
| 211 | + /** | ||
| 212 | + * Number of bits per second. | ||
| 213 | + */ | ||
| 214 | + PORT_STATS, | ||
| 215 | + | ||
| 216 | + /** | ||
| 217 | + * Custom tagged information. | ||
| 218 | + */ | ||
| 219 | + TAGGED | ||
| 220 | + } | ||
| 221 | +} |
| 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.topo; | ||
| 19 | + | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.net.LinkKey; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Collection of {@link TrafficLink}s. | ||
| 25 | + */ | ||
| 26 | +public class TrafficLinkMap extends BiLinkMap<TrafficLink> { | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public TrafficLink create(LinkKey key, Link link) { | ||
| 30 | + return new TrafficLink(key, link); | ||
| 31 | + } | ||
| 32 | +} |
-
Please register or login to post a comment