GUI2 Fixed bug of edge link not being added dynamically

Change-Id: If5a2b546f23274bbdac09a55bdd18357c72414fe
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
index 41e6090..1399847 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
@@ -511,6 +511,9 @@
         updateHost(uiHost, host);
 
         postEvent(HOST_ADDED_OR_UPDATED, uiHost, memo);
+        // Link event must be sent after the host event
+        UiEdgeLink uiEdgeLink = uiTopology.findEdgeLink(uiHost.edgeLinkId());
+        postEvent(LINK_ADDED_OR_UPDATED, uiEdgeLink, memo);
     }
 
     // invoked from UiSharedTopologyModel host listener
@@ -536,6 +539,7 @@
         if (uiHost != null) {
             UiEdgeLink edgeLink = uiTopology.findEdgeLink(uiHost.edgeLinkId());
             uiTopology.remove(edgeLink);
+            postEvent(LINK_REMOVED, edgeLink, MEMO_REMOVED);
             uiTopology.remove(uiHost);
             postEvent(HOST_REMOVED, uiHost, MEMO_REMOVED);
         } else {
diff --git a/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/ModelCacheTest.java b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/ModelCacheTest.java
index 84068ba..ea82b9a 100644
--- a/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/ModelCacheTest.java
+++ b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/ModelCacheTest.java
@@ -310,22 +310,24 @@
 
         // add a host
         cache.addOrUpdateHost(hostA);
-        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
-        dispatcher.assertEventCount(1);
+        UiLinkId hostALinkId = cache.accessHost(hostA.id()).edgeLinkId();
+        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, hostALinkId.toString());
+        dispatcher.assertEventCount(2);
         assertHostLinkCounts(1, 1);
         assertLocation(hostA.id(), DEVID_1, 101);
 
         // add a second host
         cache.addOrUpdateHost(hostB);
-        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostB.id().toString());
-        dispatcher.assertEventCount(2);
+        UiLinkId hostBLinkId = cache.accessHost(hostB.id()).edgeLinkId();
+        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, hostBLinkId.toString());
+        dispatcher.assertEventCount(4);
         assertHostLinkCounts(2, 2);
         assertLocation(hostB.id(), DEVID_1, 102);
 
         // update the first host
         cache.addOrUpdateHost(hostA);
-        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
-        dispatcher.assertEventCount(3);
+        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, hostALinkId.toString());
+        dispatcher.assertEventCount(6);
         assertHostLinkCounts(2, 2);
         assertLocation(hostA.id(), DEVID_1, 101);
 
@@ -334,7 +336,7 @@
         // remove the second host
         cache.removeHost(hostB);
         dispatcher.assertLast(Type.HOST_REMOVED, hostB.id().toString());
-        dispatcher.assertEventCount(4);
+        dispatcher.assertEventCount(8);
         assertHostLinkCounts(1, 1);
         assertNull("still host B?", cache.accessHost(hostB.id()));
 
@@ -350,7 +352,7 @@
 
         cache.moveHost(movedHost, hostA);
         dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
-        dispatcher.assertEventCount(5);
+        dispatcher.assertEventCount(9);
         assertHostLinkCounts(1, 1);
 
         assertLocation(hostA.id(), DEVID_1, 200);
@@ -362,7 +364,7 @@
 
         cache.moveHost(movedAgain, movedHost);
         dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
-        dispatcher.assertEventCount(6);
+        dispatcher.assertEventCount(10);
         assertHostLinkCounts(1, 1);
 
         assertLocation(hostA.id(), DEVID_8, 800);
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
index b4bff8e..89923ae 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
@@ -28,15 +28,10 @@
     SimpleChanges,
     ViewChildren
 } from '@angular/core';
+import {LocMeta, LogService, MetaUi, WebSocketService, ZoomUtils} from 'gui2-fw-lib';
 import {
-    LocMeta,
-    LogService,
-    MetaUi,
-    WebSocketService,
-    ZoomUtils
-} from 'gui2-fw-lib';
-import {
-    Device, DeviceProps,
+    Device,
+    DeviceProps,
     ForceDirectedGraph,
     Host,
     HostLabelToggle,
@@ -56,8 +51,8 @@
 } from './models';
 import {LocationType} from '../backgroundsvg/backgroundsvg.component';
 import {DeviceNodeSvgComponent} from './visuals/devicenodesvg/devicenodesvg.component';
-import { HostNodeSvgComponent} from './visuals/hostnodesvg/hostnodesvg.component';
-import { LinkSvgComponent} from './visuals/linksvg/linksvg.component';
+import {HostNodeSvgComponent} from './visuals/hostnodesvg/hostnodesvg.component';
+import {LinkSvgComponent} from './visuals/linksvg/linksvg.component';
 import {SelectedEvent} from './visuals/nodevisual';
 
 interface UpdateMeta {
@@ -446,7 +441,7 @@
                             .findIndex((h) => h.id === subject);
                     this.regionData.hosts[this.visibleLayerIdx()].splice(removeIdx, 1);
                     this.removeRelatedLinks(subject);
-                    this.log.warn('Host ', subject, 'removed');
+                    this.log.debug('Host ', subject, 'removed');
                 } else {
                     this.log.warn('Host removed - unexpected memo', memo);
                 }
@@ -471,11 +466,18 @@
                     const changes = ForceSvgComponent.updateObject(oldLink, <RegionLink>data);
                     this.log.debug('Link ', subject, '. Updated', changes, 'items');
                 } else {
-                    this.log.warn('Link added or updated - unexpected memo', memo);
+                    this.log.warn('Link event ignored', subject, data);
+                }
+                break;
+            case ModelEventType.LINK_REMOVED:
+                if (memo === ModelEventMemo.REMOVED) {
+                    const removeIdx = this.regionData.links.findIndex((l) => l.id === subject);
+                    this.regionData.links.splice(removeIdx, 1);
+                    this.log.debug('Link ', subject, 'removed');
                 }
                 break;
             default:
-                this.log.error('Unexpected model event', type, 'for', subject);
+                this.log.error('Unexpected model event', type, 'for', subject, 'Data', data);
         }
         this.graph.links = this.regionData.links;
         this.graph.reinitSimulation();
@@ -534,7 +536,7 @@
             links.forEach((lh) => {
                 const linkComponent: LinkSvgComponent =
                     this.links.find((l) => l.link.id === Link.linkIdFromShowHighlights(lh.id) );
-                if (linkComponent) { // A link might not be present is hosts viewing is switched off
+                if (linkComponent) { // A link might not be present if hosts viewing is switched off
                     if (fadeMs > 0) {
                         lh.fadems = fadeMs;
                     }
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/force-directed-graph.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/force-directed-graph.ts
index 312b69b..0a00f03 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/force-directed-graph.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/force-directed-graph.ts
@@ -37,6 +37,7 @@
     direct: 100,
     optical: 120,
     UiEdgeLink: 3,
+    UiDeviceLink: 100,
     _def_: 50,
 };
 
@@ -97,7 +98,7 @@
         this.simulation.nodes(this.nodes);
         this.simulation.force('link',
             d3.forceLink(this.links)
-                .strength(this.strength.bind(this))
+                .strength(LINK_STRENGTH._def_)
                 .distance(this.distance.bind(this))
         );
         this.simulation.alpha(0.3).restart();
@@ -110,16 +111,9 @@
 
     distance(link: Link) {
         const linkType = link.type;
-        this.log.debug('Link type', linkType, LINK_DISTANCE[linkType]);
         return LINK_DISTANCE[linkType] || LINK_DISTANCE._def_;
     }
 
-    strength(link: Link) {
-        const linkType = link.type;
-        this.log.debug('Link type', linkType, LINK_STRENGTH[linkType]);
-        return LINK_STRENGTH[linkType] || LINK_STRENGTH._def_;
-    }
-
     stopSimulation() {
         this.simulation.stop();
         this.log.debug('Simulation stopped');
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/node.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/node.ts
index 5b8f48d..1402f81 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/node.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/models/node.ts
@@ -276,7 +276,8 @@
     LINK_ADDED_OR_UPDATED,
     DEVICE_ADDED_OR_UPDATED,
     DEVICE_REMOVED,
-    HOST_REMOVED
+    HOST_REMOVED,
+    LINK_REMOVED,
 }
 
 /**
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
index 85ef536..c669c1c 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -57,6 +57,7 @@
     enhanced: boolean = false;
     labelPosSrc: Point = {x: 0, y: 0};
     labelPosTgt: Point = {x: 0, y: 0};
+    lastTimer: any;
 
     constructor(
         protected log: LogService,
@@ -68,16 +69,17 @@
     ngOnChanges(changes: SimpleChanges) {
         if (changes['linkHighlight']) {
             const hl: LinkHighlight = changes['linkHighlight'].currentValue;
+            clearTimeout(this.lastTimer);
             this.highlighted = hl.css;
             this.label = hl.label;
             this.isHighlighted = true;
-            this.log.debug('Link hightlighted', hl);
+            this.log.debug('Link hightlighted', this.link.id, this.highlighted);
             if (hl.fadems > 0) {
-                setTimeout(() => {
+                this.lastTimer = setTimeout(() => {
                     this.isHighlighted = false;
                     this.highlighted = '';
                     this.ref.markForCheck();
-                }, hl.fadems);
+                }, hl.fadems); // Disappear slightly before next one comes in
             }
 
         }
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
index 1f68444..304be9e 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
@@ -75,7 +75,6 @@
                         <ModelEventType><unknown>(ModelEventType[event.type]), // Number based enum
                         <ModelEventMemo>(event.memo), // String based enum
                         event.subject, event.data);
-                    this.log.debug('Region Data updated from WSS as topo2UiModelEvent', event.subject, event.data);
                 }
             ],
             ['showHighlights', (event) => {
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
index 97b8764..d8e0a0f 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
@@ -697,7 +697,6 @@
     nodeSelected(nodesOrLink: UiElement[]) {
         this.details.ngOnChanges({'selectedNodes':
             new SimpleChange(undefined, nodesOrLink, true)});
-        this.trs.cancelTraffic();
     }
 
     /**