TeTopology core and nbi bug fixes and improvements

Change-Id: I5f3dbcaa79b04c1b1b00b9df7ccae804953c3bae
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
index 4f75d76..3d6be15 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
@@ -39,6 +39,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
@@ -137,7 +138,7 @@
     implements TeTopologyStore {
     private static final String STORE_NAME = "TE_NETWORK_TOPOLOGY_STORE";
     private static final String TETOPOLOGYKEY_INTERNALTETOPOLOGY = "TeTopologyKey-InternalTeTopology";
-    private static final String NETWORKID_NETWORK = "NetworkId-Network";
+    private static final String NETWORKID_NETWORK = "NetworkId-InternalNetwork";
     private static final String TENODEKEY_INTERNALTENODE = "TeNodeKey-InternalTeNode";
     private static final String CONNMATRIXKEY_CONNECTIVITYMATRIX = "ConnMatrixKey-ConnectivityMatrix";
     private static final String NETWORKNODEKEY_INTERNALNETWORKNODE = "NetworkNodeKey-InternalNetworkNode";
@@ -199,7 +200,8 @@
     // Track termination point keys by TE termination point Key
     private ConsistentMap<TeLinkTpGlobalKey, TerminationPointKey> tpKeyConsistentMap;
     private Map<TeLinkTpGlobalKey, TerminationPointKey> tpKeyMap;
-    private BlockingQueue<TeTopologyMapEvent> mapEventQueue;
+    private final BlockingQueue<TeTopologyMapEvent> mapEventQueue = new LinkedBlockingQueue<>();
+
     private long providerId;
     private static final Serializer TETOPOLOGY_SERIALIZER = Serializer
             .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
@@ -373,6 +375,7 @@
         tpKeyMap.clear();
         ttpConsistentMap.destroy();
         ttpMap.clear();
+        mapEventQueue.clear();
         log.info("Stopped");
     }
 
@@ -454,10 +457,6 @@
     private class InternalTeNodeListener implements MapEventListener<TeNodeKey, InternalTeNode> {
         @Override
         public void event(MapEvent<TeNodeKey, InternalTeNode> event) {
-            // Event should be ignored when the topology is not there.
-            if (teTopologyMap.get(event.key().teTopologyKey()) == null) {
-                return;
-            }
             Type type = null;
             switch (event.type()) {
             case INSERT:
@@ -499,10 +498,6 @@
     private class InternalNetworkNodeListener implements MapEventListener<NetworkNodeKey, InternalNetworkNode> {
         @Override
         public void event(MapEvent<NetworkNodeKey, InternalNetworkNode> event) {
-            // Event should be ignored when the network is not there.
-            if (networkMap.get(event.key().networkId()) == null) {
-                return;
-            }
             Type type = null;
             switch (event.type()) {
             case INSERT:
@@ -544,11 +539,6 @@
     private class InternalTeLinkListener implements MapEventListener<TeLinkTpGlobalKey, InternalTeLink> {
         @Override
         public void event(MapEvent<TeLinkTpGlobalKey, InternalTeLink> event) {
-            // Event should be ignored when the topology or locol node is not there.
-            if (teTopologyMap.get(event.key().teTopologyKey()) == null ||
-                    teNodeMap.get(event.key().teNodeKey()) == null) {
-                return;
-            }
             Type type = null;
             switch (event.type()) {
             case INSERT:
@@ -589,10 +579,6 @@
     private class InternalNetworkLinkListener implements MapEventListener<NetworkLinkKey, InternalNetworkLink> {
         @Override
         public void event(MapEvent<NetworkLinkKey, InternalNetworkLink> event) {
-            // Event should be ignored when the network is not there.
-            if (networkMap.get(event.key().networkId()) == null) {
-                return;
-            }
             Type type = null;
             switch (event.type()) {
             case INSERT:
@@ -819,6 +805,7 @@
 
     @Override
     public void updateNetwork(Network network) {
+        log.debug("updateNetwork {}", network);
         InternalNetwork curNetwork = networkMap.get(network.networkId());
         TeTopologyKey topoKey = null;
         if (network.teTopologyId() != null) {
@@ -1415,8 +1402,8 @@
     }
 
     @Override
-    public void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue) {
-        mapEventQueue = queue;
+    public BlockingQueue<TeTopologyMapEvent> mapEventQueue() {
+        return mapEventQueue;
     }
 
     @Override
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyConfig.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyConfig.java
index b980159..a4e6032 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyConfig.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyConfig.java
@@ -31,12 +31,12 @@
     private static final String TENODE_ID_END = "tenode-id-end";
 
     /**
-      * Retrieves TE topology provider identifier.
-      *
-      * @return provider Id
-      * @throws ConfigException if the parameters are not correctly configured
-      * or conversion of the parameters fails
-      */
+     * Retrieves TE topology provider identifier.
+     *
+     * @return provider Id
+     * @throws ConfigException if the parameters are not correctly configured
+     * or conversion of the parameters fails
+     */
     public long providerId() throws ConfigException {
         try {
             return object.path(PROVIDER_ID).asLong();
@@ -45,49 +45,49 @@
         }
     }
 
-    /**
-     * Retrieves TE node starting IPv4 address.
-     *
-     * @return the IPv4 address
-     * @throws ConfigException if the parameters are not correctly configured
-     * or conversion of the parameters fails
-     */
-    public Ip4Address teNodeIpStart() throws ConfigException {
+   /**
+    * Retrieves TE node starting IPv4 address.
+    *
+    * @return the IPv4 address
+    * @throws ConfigException if the parameters are not correctly configured
+    * or conversion of the parameters fails
+    */
+   public Ip4Address teNodeIpStart() throws ConfigException {
        try {
            return Ip4Address.valueOf(object.path(TENODE_ID_START).asText());
        } catch (IllegalArgumentException e) {
            throw new ConfigException(CONFIG_VALUE_ERROR, e);
        }
-    }
+   }
 
-    /**
-     * Retrieves TE node end IPv4 address.
-     *
-     * @return the IPv4 address
-     * @throws ConfigException if the parameters are not correctly configured or
-     *             conversion of the parameters fails
-     */
-    public Ip4Address teNodeIpEnd() throws ConfigException {
-        try {
-            return Ip4Address.valueOf(object.path(TENODE_ID_END).asText());
-        } catch (IllegalArgumentException e) {
-            throw new ConfigException(CONFIG_VALUE_ERROR, e);
-        }
-    }
+  /**
+   * Retrieves TE node end IPv4 address.
+   *
+   * @return the IPv4 address
+   * @throws ConfigException if the parameters are not correctly configured
+   * or conversion of the parameters fails
+   */
+  public Ip4Address teNodeIpEnd() throws ConfigException {
+      try {
+          return Ip4Address.valueOf(object.path(TENODE_ID_END).asText());
+      } catch (IllegalArgumentException e) {
+          throw new ConfigException(CONFIG_VALUE_ERROR, e);
+      }
+  }
 
-    /**
-     * Retrieves if this is a MDSC(Multi-Domain Super Controller).
-     *
-     * @return MDSC value
-     * @throws ConfigException if the parameters are not correctly configured or
-     *             conversion of the parameters fails
-     */
-    public String mdsc() throws ConfigException {
-        try {
-            return object.path(MDSC).asText();
-        } catch (IllegalArgumentException e) {
-            throw new ConfigException(CONFIG_VALUE_ERROR, e);
-        }
-    }
+  /**
+   * Retrieves if this is a MDSC(Multi-Domain Super Controller).
+   *
+   * @return MDSC value
+   * @throws ConfigException if the parameters are not correctly configured or
+   *             conversion of the parameters fails
+   */
+  public String mdsc() throws ConfigException {
+      try {
+          return object.path(MDSC).asText();
+      } catch (IllegalArgumentException e) {
+          throw new ConfigException(CONFIG_VALUE_ERROR, e);
+      }
+  }
 
 }
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
index 1407e0c..30ca4e2 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
@@ -40,6 +40,7 @@
 import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_UPDATED;
 import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_ADDED;
 import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_REMOVED;
+import static org.onosproject.tetopology.management.api.link.TeLink.BIT_ACCESS_INTERDOMAIN;
 import static org.onosproject.tetopology.management.impl.TeMgrUtil.linkBuilder;
 import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkBuilder;
 import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkLinkKey;
@@ -51,9 +52,7 @@
 import java.util.BitSet;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
@@ -113,6 +112,7 @@
 import org.onosproject.tetopology.management.api.node.CommonNodeData;
 import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
 import org.onosproject.tetopology.management.api.node.DefaultTeNode;
+import org.onosproject.tetopology.management.api.node.DefaultTunnelTerminationPoint;
 import org.onosproject.tetopology.management.api.node.NetworkNode;
 import org.onosproject.tetopology.management.api.node.NetworkNodeEventSubject;
 import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
@@ -176,8 +176,6 @@
     public TeTopologyStore store;
 
     private TeTopologyStoreDelegate delegate = this::post;
-    private final BlockingQueue<TeTopologyEvent> eventQueue = new LinkedBlockingQueue<>();
-    private final BlockingQueue<TeTopologyMapEvent> mapEventQueue = new LinkedBlockingQueue<>();
     private final ConfigFactory<ApplicationId, TeTopologyConfig> factory =
             new ConfigFactory<ApplicationId, TeTopologyConfig>(APP_SUBJECT_FACTORY,
                     TeTopologyConfig.class,
@@ -205,7 +203,6 @@
      */
     public void activateBasics() {
         store.setDelegate(delegate);
-        store.setMapEventQueue(mapEventQueue);
         store.setProviderId(providerId);
         eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry);
     }
@@ -238,7 +235,6 @@
         cfgService.unregisterConfigFactory(factory);
         executor.shutdownNow();
         executor = null;
-        eventQueue.clear();
         log.info("Stopped");
     }
 
@@ -315,7 +311,7 @@
         public void run() {
             try {
                 TeTopologyMapEvent event;
-                while ((event = mapEventQueue.take()) != null) {
+                while ((event = store.mapEventQueue().take()) != null) {
                     switch (event.type()) {
                     case TE_TOPOLOGY_ADDED:
                     case TE_TOPOLOGY_UPDATED:
@@ -335,6 +331,10 @@
                         break;
                     case TE_NODE_ADDED:
                     case TE_NODE_UPDATED:
+                        if (store.teTopology(event.teNodeKey().teTopologyKey()) == null) {
+                            // Event should be ignored when the topology is not there.
+                            break;
+                        }
                         TeNode teNode = store.teNode(event.teNodeKey());
                         post(new TeTopologyEvent(event.type(),
                                                  new TeNodeEventSubject(event.teNodeKey(), teNode)));
@@ -344,6 +344,10 @@
                         }
                         break;
                     case TE_NODE_REMOVED:
+                        if (store.teTopology(event.teNodeKey().teTopologyKey()) == null) {
+                            // Event should be ignored when the topology is not there.
+                            break;
+                        }
                         post(new TeTopologyEvent(TE_NODE_REMOVED,
                                                  new TeNodeEventSubject(event.teNodeKey(), null)));
                         if (mdsc && isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
@@ -352,6 +356,11 @@
                         break;
                     case TE_LINK_ADDED:
                     case TE_LINK_UPDATED:
+                        if (store.teTopology(event.teLinkKey().teTopologyKey()) == null ||
+                                store.teNode(event.teLinkKey().teNodeKey()) == null) {
+                            // Event should be ignored when the topology or node is not there.
+                            break;
+                        }
                         TeLink teLink = store.teLink(event.teLinkKey());
                         post(new TeTopologyEvent(event.type(),
                                                  new TeLinkEventSubject(event.teLinkKey(), teLink)));
@@ -362,6 +371,11 @@
                         }
                         break;
                     case TE_LINK_REMOVED:
+                        if (store.teTopology(event.teLinkKey().teTopologyKey()) == null ||
+                                store.teNode(event.teLinkKey().teNodeKey()) == null) {
+                            // Event should be ignored when the topology or node is not there.
+                            break;
+                        }
                         post(new TeTopologyEvent(TE_LINK_REMOVED,
                                                  new TeLinkEventSubject(event.teLinkKey(), null)));
                         if (mdsc && isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
@@ -382,21 +396,37 @@
                         break;
                     case NODE_ADDED:
                     case NODE_UPDATED:
+                        if (store.network(event.networkNodeKey().networkId()) == null) {
+                            // Event should be ignored when the network is not there.
+                            break;
+                        }
                         NetworkNode node = store.networkNode(event.networkNodeKey());
                         post(new TeTopologyEvent(event.type(),
                                                  new NetworkNodeEventSubject(event.networkNodeKey(), node)));
                         break;
                     case NODE_REMOVED:
+                        if (store.network(event.networkNodeKey().networkId()) == null) {
+                            // Event should be ignored when the network is not there.
+                            break;
+                        }
                         post(new TeTopologyEvent(NODE_REMOVED,
                                                  new NetworkNodeEventSubject(event.networkNodeKey(), null)));
                         break;
                     case LINK_ADDED:
                     case LINK_UPDATED:
+                        if (store.network(event.networkLinkKey().networkId()) == null) {
+                            // Event should be ignored when the network is not there.
+                            break;
+                        }
                         NetworkLink link = store.networkLink(event.networkLinkKey());
                         post(new TeTopologyEvent(event.type(),
                                                  new NetworkLinkEventSubject(event.networkLinkKey(), link)));
                         break;
                     case LINK_REMOVED:
+                        if (store.network(event.networkLinkKey().networkId()) == null) {
+                            // Event should be ignored when the network is not there.
+                            break;
+                        }
                         post(new TeTopologyEvent(LINK_REMOVED,
                                                  new NetworkLinkEventSubject(event.networkLinkKey(), null)));
                         break;
@@ -452,7 +482,21 @@
                                                    srcNode.opStatus(), srcNode.flags()); // No change
         Map<Long, ConnectivityMatrix> connMatrices = srcNode.connectivityMatrices();
         List<Long> teLinkIds = srcNode.teLinkIds(); // No change
-        Map<Long, TunnelTerminationPoint> ttps = srcNode.tunnelTerminationPoints();
+        Map<Long, TunnelTerminationPoint> ttps = null;
+        if (MapUtils.isNotEmpty(srcNode.tunnelTerminationPoints())) {
+            ttps = Maps.newHashMap();
+            for (Map.Entry<Long, TunnelTerminationPoint> entry : srcNode.tunnelTerminationPoints().entrySet()) {
+                TunnelTerminationPoint ttp = entry.getValue();
+                ttps.put(entry.getKey(),
+                         new DefaultTunnelTerminationPoint(ttp.ttpId(), ttp.switchingLayer(),
+                                                           ttp.encodingLayer(), ttp.flags(),
+                                                           ttp.interLayerLockList(),
+                                                           ttp.localLinkConnectivityList(),
+                                                           ttp.availAdaptBandwidth(),
+                                                           null)); //Remove supporting TTP Ids
+            }
+        }
+
         List<Long> teTpIds = srcNode.teTerminationPointIds(); // No change
         DefaultTeNode newNode = new DefaultTeNode(mergedTeNodeId, underlayTopologyId,
                 supportTeNodeId, sourceTeNodeId, common, connMatrices, teLinkIds,
@@ -504,8 +548,21 @@
                                                     exLink.maxAvailLspBandwidth(),
                                                     exLink.minAvailLspBandwidth(),
                                                     exLink.oduResource());
+        BitSet flags = exLink.flags();
+        if (peerTeLinkKey != null &&
+                externalLink != null && externalLink.plugId() != null) {
+            // Assuming this is an inter-domain link which is merged with its peer,
+            // needs to clear BIT_ACCESS_INTERDOMAIN
+            flags.clear(BIT_ACCESS_INTERDOMAIN);
+        } else if (peerTeLinkKey == null &&
+                externalLink != null && externalLink.plugId() != null) {
+            // Assuming this is an inter-domain link which lost its peer,
+            // needs to clear BIT_ACCESS_INTERDOMAIN
+            flags.set(BIT_ACCESS_INTERDOMAIN);
+        }
+
         CommonLinkData common = new CommonLinkData(exLink.adminStatus(), exLink.opStatus(),
-                exLink.flags(), exLink.switchingLayer(), exLink.encodingLayer(),
+                flags, exLink.switchingLayer(), exLink.encodingLayer(),
                 externalLink, underlayPath, teAttributes,
                 exLink.administrativeGroup(), exLink.interLayerLocks(),
                 bandwidth);
@@ -793,19 +850,18 @@
                 teNodeIpEnd = cfgService.getConfig(appId, TeTopologyConfig.class)
                                         .teNodeIpEnd();
                 mdsc = cfgService.getConfig(appId, TeTopologyConfig.class)
-                                 .mdsc().equalsIgnoreCase(MDSC_MODE);
+                        .mdsc().equals(MDSC_MODE);
                 nextTeNodeId = teNodeIpStart.toInt();
             } catch (ConfigException e) {
                 log.error("Configuration error {}", e);
             }
         }
 
-
         @Override
         public boolean isRelevant(NetworkConfigEvent event) {
             return event.configClass().equals(TeTopologyConfig.class) &&
                     (event.type() == CONFIG_ADDED ||
-                     event.type() == CONFIG_UPDATED);
+                    event.type() == CONFIG_UPDATED);
         }
     }
 
@@ -826,6 +882,7 @@
     @Override
     public TeTopology teTopology(TeTopologyKey topologyId) {
         if (mergedTopology != null &&
+                topologyId != null &&
                 topologyId.equals(mergedTopologyKey)) {
             return mergedTopology;
         }
@@ -955,4 +1012,9 @@
                                                       KeyId.keyId(Long.toString(teTpKey.teLinkTpId()))) :
                store.terminationPointKey(teTpKey);
     }
+
+    @Override
+    public long teContollerId() {
+        return providerId;
+    }
 }
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStore.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStore.java
index bede7b3..09b8db7 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStore.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStore.java
@@ -274,11 +274,11 @@
     void setNextTeNodeId(TeTopologyKey topologyKey, long nextNodeId);
 
     /**
-     * Sets the queue to store the events originating from consistent maps.
+     * Returns the queue to store the events originating from consistent maps.
      *
-     * @param queue a blocking queue
+     * @return value of the blocking queue
      */
-    void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue);
+    BlockingQueue<TeTopologyMapEvent> mapEventQueue();
 
     /**
      * Sets the provider ID.
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
index 8ce1241..9ed72ba 100644
--- a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
@@ -113,7 +113,7 @@
                                                  EncodingType.LSP_ENCODING_ODUK,
                                                  new BitSet(TeConstants.FLAG_MAX_BITS),
                                                  null, null,
-                                                 ODU2BW); //10G for ODU2
+                                                 ODU2BW, null); //10G for ODU2
     }
 
     private static TerminationPoint tpBuilder(long teTpId) {
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
index 7f4bb80..f4ff72d 100644
--- a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
@@ -1026,12 +1026,13 @@
     }
 
     @Override
-    public void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue) {
+    public void setProviderId(long providerId) {
+        this.providerId = providerId;
     }
 
     @Override
-    public void setProviderId(long providerId) {
-        this.providerId = providerId;
+    public BlockingQueue<TeTopologyMapEvent> mapEventQueue() {
+        return null;
     }
 }
 
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/TeTopologyManagerTest.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/TeTopologyManagerTest.java
index 03d21fb..f6c0db0 100644
--- a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/TeTopologyManagerTest.java
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/TeTopologyManagerTest.java
@@ -128,6 +128,7 @@
                 .teNode(new TeNodeKey(DefaultBuilder.teTopologyKey(),
                                       DefaultBuilder.teNode().teNodeId()));
         assertNotNull("TeNode should be found", teNode);
+        assertTrue("TE node should be identical", teNode.equals(DefaultBuilder.teNode()));
         assertTrue("Number of TTPs should be 1",
                    teNode.tunnelTerminationPoints().size() == 1);
         TeLink teLink = service