Enhancement of tetopology implementation

To support regualar network and TE topology

Change-Id: Ib8319212d775c78f49a86a7b7685759099189967
diff --git a/apps/tetopology/BUCK b/apps/tetopology/BUCK
index 9ccc662..e818418 100644
--- a/apps/tetopology/BUCK
+++ b/apps/tetopology/BUCK
@@ -3,6 +3,7 @@
 ]
 
 onos_app (
+    app_name = 'org.onosproject.tetopology',
     title = 'TE Topology Core App',
     category = 'ACTN',
     url = 'http://onosproject.org',
diff --git a/apps/tetopology/app/BUCK b/apps/tetopology/app/BUCK
new file mode 100644
index 0000000..61376a4
--- /dev/null
+++ b/apps/tetopology/app/BUCK
@@ -0,0 +1,17 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//apps/tetopology/api:onos-apps-tetopology-api',
+    '//incubator/api:onos-incubator-api',
+    '//core/store/serializers:onos-core-serializers',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//utils/osgi:onlab-osgi-tests',
+    '//incubator/api:onos-incubator-api-tests',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+)
diff --git a/apps/tetopology/app/app.xml b/apps/tetopology/app/app.xml
new file mode 100644
index 0000000..e675d4c
--- /dev/null
+++ b/apps/tetopology/app/app.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2015 Open Networking Laboratory
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<app name="org.onosproject.tetopology" origin="HUAWEI" version="${project.version}"
+     featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+     features="${project.artifactId}">
+    <description>${project.description}</description>
+    <artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
+</app>
+
diff --git a/apps/tetopology/app/features.xml b/apps/tetopology/app/features.xml
new file mode 100644
index 0000000..b22a210
--- /dev/null
+++ b/apps/tetopology/app/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ Copyright 2015 Open Networking Laboratory
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+        <bundle>mvn:${project.groupId}/onos-app-tetopology-api/${project.version}</bundle>
+        <bundle>mvn:${project.groupId}/onos-app-tetopology/${project.version}</bundle>
+    </feature>
+</features>
diff --git a/apps/tetopology/app/pom.xml b/apps/tetopology/app/pom.xml
new file mode 100644
index 0000000..0566e85
--- /dev/null
+++ b/apps/tetopology/app/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-present Open Networking Laboratory
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-tetopology</artifactId>
+        <version>1.8.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-app-tetopology</artifactId>
+    <version>1.8.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <description>IETF TE topology application</description>
+
+    <dependencies>
+ 
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-tetopology-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+         <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-serializers</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava-testlib</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-osgi</artifactId>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+         <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-common</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+ 
+    </dependencies>
+</project>
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
new file mode 100644
index 0000000..e3284b3
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
@@ -0,0 +1,1413 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_REMOVED;
+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.TeTopologyEvent.Type.TE_TOPOLOGY_UPDATED;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.BitSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.AtomicCounter;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.tetopology.management.api.CommonTopologyData;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.DefaultTeTopologies;
+import org.onosproject.tetopology.management.api.DefaultTeTopology;
+import org.onosproject.tetopology.management.api.EncodingType;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.LongValue;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.OptimizationType;
+import org.onosproject.tetopology.management.api.ProviderClientId;
+import org.onosproject.tetopology.management.api.SwitchingType;
+import org.onosproject.tetopology.management.api.TeConstants;
+import org.onosproject.tetopology.management.api.TeStatus;
+import org.onosproject.tetopology.management.api.TeTopologies;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyEvent.Type;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.TeUtils;
+import org.onosproject.tetopology.management.api.link.AsNumber;
+import org.onosproject.tetopology.management.api.link.CommonLinkData;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.DefaultTeLink;
+import org.onosproject.tetopology.management.api.link.ElementType;
+import org.onosproject.tetopology.management.api.link.ExternalLink;
+import org.onosproject.tetopology.management.api.link.Label;
+import org.onosproject.tetopology.management.api.link.LinkBandwidth;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.OduResource;
+import org.onosproject.tetopology.management.api.link.PathElement;
+import org.onosproject.tetopology.management.api.link.TeIpv4;
+import org.onosproject.tetopology.management.api.link.TeIpv6;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.link.TePathAttributes;
+import org.onosproject.tetopology.management.api.link.TunnelProtectionType;
+import org.onosproject.tetopology.management.api.link.UnderlayAbstractPath;
+import org.onosproject.tetopology.management.api.link.UnderlayBackupPath;
+import org.onosproject.tetopology.management.api.link.UnderlayPath;
+import org.onosproject.tetopology.management.api.link.UnderlayPrimaryPath;
+import org.onosproject.tetopology.management.api.link.UnnumberedLink;
+import org.onosproject.tetopology.management.api.node.CommonNodeData;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrixKey;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTeNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.DefaultTunnelTerminationPoint;
+import org.onosproject.tetopology.management.api.node.LocalLinkConnectivity;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.NodeTpKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+import org.slf4j.Logger;
+
+import com.esotericsoftware.kryo.serializers.JavaSerializer;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Implementation of the TE network store.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedTeTopologyStore
+    extends AbstractStore<TeTopologyEvent, TeTopologyStoreDelegate>
+    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 TENODEKEY_INTERNALTENODE = "TeNodeKey-InternalTeNode";
+    private static final String CONNMATRIXKEY_CONNECTIVITYMATRIX = "ConnMatrixKey-ConnectivityMatrix";
+    private static final String NETWORKNODEKEY_INTERNALNETWORKNODE = "NetworkNodeKey-InternalNetworkNode";
+    private static final String TELINKGLOBALKEY_INTERNALTELINK = "TeLinkGlobalKey-InternalTeLink";
+    private static final String NETWORKLINKKEY_INTERNALNETWORKLINK = "NetworkLinkKey-InternalNetworkLink";
+    private static final String TPKEY_INTERNALTERMINATIONPOINT = "tpKey-InternalTerminationPoint";
+    private static final String TELINKTPGLOBALKEY_TERMINATIONPOINTKEY = "TeLinkGlobalKey-TerminationPointKey";
+    private static final String TTPKEY_TUNNELTERMINATIONPOINT = "TtpKey-TunnelTerminationPoint";
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+    // Track TE topologies by TE Topology key
+    private ConsistentMap<TeTopologyKey, InternalTeTopology> teTopologyConsistentMap;
+    private Map<TeTopologyKey, InternalTeTopology> teTopologyMap;
+    private AtomicCounter nextTeTopologyId;
+     // Listener for te topology events
+    private final MapEventListener<TeTopologyKey, InternalTeTopology> teTopologyListener =
+            new InternalTeTopologyListener();
+    // Track networks by network Id
+    private ConsistentMap<KeyId, InternalNetwork> networkConsistentMap;
+    private Map<KeyId, InternalNetwork> networkMap;
+    // Listener for network events
+    private final MapEventListener<KeyId, InternalNetwork> networkListener =
+            new InternalNetworkListener();
+    // Track TE nodes by TE node key
+    private ConsistentMap<TeNodeKey, InternalTeNode> teNodeConsistentMap;
+    private Map<TeNodeKey, InternalTeNode> teNodeMap;
+    // Track ConnectivityMatrix by its key
+    private ConsistentMap<ConnectivityMatrixKey, ConnectivityMatrix> connMatrixConsistentMap;
+    private Map<ConnectivityMatrixKey, ConnectivityMatrix> connMatrixMap;
+    // Track Tunnel Termination Points by its key
+    private ConsistentMap<TtpKey, TunnelTerminationPoint> ttpConsistentMap;
+    private Map<TtpKey, TunnelTerminationPoint> ttpMap;
+    // Listener for TE node events
+    private final MapEventListener<TeNodeKey, InternalTeNode> teNodeListener =
+            new InternalTeNodeListener();
+    // Track network nodes by network node key
+    private ConsistentMap<NetworkNodeKey, InternalNetworkNode> networkNodeConsistentMap;
+    private Map<NetworkNodeKey, InternalNetworkNode> networkNodeMap;
+    // Listener for network node events
+    private final MapEventListener<NetworkNodeKey, InternalNetworkNode> networkNodeListener =
+            new InternalNetworkNodeListener();
+    // Track TE links by its key
+    private ConsistentMap<TeLinkTpGlobalKey, InternalTeLink> teLinkConsistentMap;
+    private Map<TeLinkTpGlobalKey, InternalTeLink> teLinkMap;
+    // Listener for te link events
+    private final MapEventListener<TeLinkTpGlobalKey, InternalTeLink> teLinkListener =
+        new InternalTeLinkListener();
+    // Track network links by network link key
+    private ConsistentMap<NetworkLinkKey, InternalNetworkLink> networkLinkConsistentMap;
+    private Map<NetworkLinkKey, InternalNetworkLink> networkLinkMap;
+    // Listener for network link events
+    private final MapEventListener<NetworkLinkKey, InternalNetworkLink> networkLinkListener =
+            new InternalNetworkLinkListener();
+    // Track Termination points by termination point key
+    private ConsistentMap<TerminationPointKey, InternalTerminationPoint> tpConsistentMap;
+    private Map<TerminationPointKey, InternalTerminationPoint> tpMap;
+    // Track termination point keys by TE termination point Key
+    private ConsistentMap<TeLinkTpGlobalKey, TerminationPointKey> tpKeyConsistentMap;
+    private Map<TeLinkTpGlobalKey, TerminationPointKey> tpKeyMap;
+    private BlockingQueue<TeTopologyMapEvent> mapEventQueue;
+    private static final Serializer TETOPOLOGY_SERIALIZER = Serializer
+            .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
+                    .register(TeTopologyKey.class)
+                    .register(ProviderClientId.class)
+                    .register(TeNodeKey.class)
+                    .register(TeLinkTpGlobalKey.class)
+                    .register(CommonTopologyData.class)
+                    .register(KeyId.class)
+                    .register(OptimizationType.class)
+                    .register(new JavaSerializer(), BitSet.class)
+                    .register(InternalTeTopology.class)
+                    .register(InternalNetwork.class)
+                    .register(InternalTerminationPoint.class)
+                    .register(InternalTeNode.class)
+                    .register(InternalNetworkNode.class)
+                    .register(CommonNodeData.class)
+                    .register(ConnectivityMatrixKey.class)
+                    .register(ConnectivityMatrix.class)
+                    .register(TtpKey.class)
+                    .register(NetworkNodeKey.class)
+                    .register(TeStatus.class)
+                    .register(ElementType.class)
+                    .register(TeIpv4.class)
+                    .register(TeIpv6.class)
+                    .register(AsNumber.class)
+                    .register(Label.class)
+                    .register(UnnumberedLink.class)
+                    .register(InternalTeLink.class)
+                    .register(InternalNetworkLink.class)
+                    .register(TeLinkTpKey.class)
+                    .register(NetworkLinkKey.class)
+                    .register(NodeTpKey.class)
+                    .register(CommonLinkData.class)
+                    .register(SwitchingType.class)
+                    .register(EncodingType.class)
+                    .register(ExternalLink.class)
+                    .register(UnderlayPath.class)
+                    .register(LinkBandwidth.class)
+                    .register(OduResource.class)
+                    .register(PathElement.class)
+                    .register(UnderlayAbstractPath.class)
+                    .register(UnderlayBackupPath.class)
+                    .register(UnderlayPrimaryPath.class)
+                    .register(TePathAttributes.class)
+                    .register(TerminationPoint.class)
+                    .register(TunnelTerminationPoint.class)
+                    .register(DefaultTunnelTerminationPoint.class)
+                    .register(TerminationPointKey.class)
+                    .register(TunnelProtectionType.class)
+                    .register(LongValue.class)
+                    .register(LocalLinkConnectivity.class)
+                    .build());
+
+    /**
+     * Distributed network store service activate method.
+     */
+    @Activate
+    public void activate() {
+        teTopologyConsistentMap = storageService
+                .<TeTopologyKey, InternalTeTopology>consistentMapBuilder()
+                .withSerializer(TETOPOLOGY_SERIALIZER)
+                .withName(TETOPOLOGYKEY_INTERNALTETOPOLOGY)
+                .withRelaxedReadConsistency()
+                .build();
+        teTopologyConsistentMap.addListener(teTopologyListener);
+        teTopologyMap = teTopologyConsistentMap.asJavaMap();
+        networkConsistentMap = storageService
+                .<KeyId, InternalNetwork>consistentMapBuilder()
+                .withSerializer(TETOPOLOGY_SERIALIZER)
+                .withName(NETWORKID_NETWORK)
+                .withRelaxedReadConsistency()
+                .build();
+        networkConsistentMap.addListener(networkListener);
+        networkMap = networkConsistentMap.asJavaMap();
+        teNodeConsistentMap = storageService
+                .<TeNodeKey, InternalTeNode>consistentMapBuilder()
+                .withSerializer(TETOPOLOGY_SERIALIZER)
+                .withName(TENODEKEY_INTERNALTENODE)
+                .withRelaxedReadConsistency()
+                .build();
+        teNodeConsistentMap.addListener(teNodeListener);
+        teNodeMap = teNodeConsistentMap.asJavaMap();
+        connMatrixConsistentMap = storageService
+                 .<ConnectivityMatrixKey, ConnectivityMatrix>consistentMapBuilder()
+                 .withSerializer(TETOPOLOGY_SERIALIZER)
+                 .withName(CONNMATRIXKEY_CONNECTIVITYMATRIX)
+                 .withRelaxedReadConsistency()
+                 .build();
+        connMatrixMap = connMatrixConsistentMap.asJavaMap();
+        networkNodeConsistentMap = storageService
+                 .<NetworkNodeKey, InternalNetworkNode>consistentMapBuilder()
+                 .withSerializer(TETOPOLOGY_SERIALIZER)
+                 .withName(NETWORKNODEKEY_INTERNALNETWORKNODE)
+                 .withRelaxedReadConsistency()
+                 .build();
+        networkNodeConsistentMap.addListener(networkNodeListener);
+        networkNodeMap = networkNodeConsistentMap.asJavaMap();
+        teLinkConsistentMap = storageService
+                 .<TeLinkTpGlobalKey, InternalTeLink>consistentMapBuilder()
+                 .withSerializer(TETOPOLOGY_SERIALIZER)
+                 .withName(TELINKGLOBALKEY_INTERNALTELINK)
+                 .withRelaxedReadConsistency()
+                 .build();
+        teLinkConsistentMap.addListener(teLinkListener);
+        teLinkMap = teLinkConsistentMap.asJavaMap();
+        networkLinkConsistentMap = storageService
+                 .<NetworkLinkKey, InternalNetworkLink>consistentMapBuilder()
+                 .withSerializer(TETOPOLOGY_SERIALIZER)
+                 .withName(NETWORKLINKKEY_INTERNALNETWORKLINK)
+                 .withRelaxedReadConsistency()
+                 .build();
+        networkLinkConsistentMap.addListener(networkLinkListener);
+        networkLinkMap = networkLinkConsistentMap.asJavaMap();
+        tpConsistentMap = storageService
+                 .<TerminationPointKey, InternalTerminationPoint>consistentMapBuilder()
+                 .withSerializer(TETOPOLOGY_SERIALIZER)
+                 .withName(TPKEY_INTERNALTERMINATIONPOINT)
+                 .withRelaxedReadConsistency()
+                 .build();
+        tpMap = tpConsistentMap.asJavaMap();
+        tpKeyConsistentMap = storageService
+                  .<TeLinkTpGlobalKey, TerminationPointKey>consistentMapBuilder()
+                  .withSerializer(TETOPOLOGY_SERIALIZER)
+                  .withName(TELINKTPGLOBALKEY_TERMINATIONPOINTKEY)
+                  .withRelaxedReadConsistency()
+                  .build();
+        tpKeyMap = tpKeyConsistentMap.asJavaMap();
+        ttpConsistentMap = storageService
+                  .<TtpKey, TunnelTerminationPoint>consistentMapBuilder()
+                  .withSerializer(TETOPOLOGY_SERIALIZER)
+                  .withName(TTPKEY_TUNNELTERMINATIONPOINT)
+                  .withRelaxedReadConsistency()
+                  .build();
+        ttpMap = ttpConsistentMap.asJavaMap();
+
+        nextTeTopologyId = storageService.getAtomicCounter("COUNTER_NAME");
+        log.info("Started");
+    }
+
+    /**
+     * Distributed network store service deactivate method.
+     */
+    @Deactivate
+    public void deactivate() {
+        teTopologyConsistentMap.removeListener(teTopologyListener);
+        teTopologyConsistentMap.destroy();
+        teTopologyMap.clear();
+        networkConsistentMap.removeListener(networkListener);
+        networkConsistentMap.destroy();
+        networkMap.clear();
+        teNodeConsistentMap.removeListener(teNodeListener);
+        teNodeConsistentMap.destroy();
+        teNodeMap.clear();
+        connMatrixConsistentMap.destroy();
+        connMatrixMap.clear();
+        networkNodeConsistentMap.destroy();
+        networkNodeConsistentMap.removeListener(networkNodeListener);
+        networkNodeMap.clear();
+        teLinkConsistentMap.removeListener(teLinkListener);
+        teLinkConsistentMap.destroy();
+        teLinkMap.clear();
+        networkLinkConsistentMap.destroy();
+        networkLinkConsistentMap.removeListener(networkLinkListener);
+        networkLinkMap.clear();
+        tpConsistentMap.destroy();
+        tpMap.clear();
+        tpKeyConsistentMap.destroy();
+        tpKeyMap.clear();
+        ttpConsistentMap.destroy();
+        ttpMap.clear();
+        log.info("Stopped");
+    }
+
+    /**
+     * Listener class to map listener map events to the TETOPOLOGY events.
+     */
+    private class InternalTeTopologyListener implements MapEventListener<TeTopologyKey, InternalTeTopology> {
+        @Override
+        public void event(MapEvent<TeTopologyKey, InternalTeTopology> event) {
+            Type type = null;
+            switch (event.type()) {
+            case INSERT:
+                type = TE_TOPOLOGY_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().childUpdate()) {
+                    // Masked by the child events (e.g. Removal)
+                    break;
+                }
+                type = TE_TOPOLOGY_UPDATED;
+                break;
+            case REMOVE:
+                type = TE_TOPOLOGY_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setTeTopologyKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener class to map listener map events to the network events.
+     */
+    private class InternalNetworkListener implements MapEventListener<KeyId, InternalNetwork> {
+        @Override
+        public void event(MapEvent<KeyId, InternalNetwork> event) {
+            Type type = null;
+            switch (event.type()) {
+            case INSERT:
+                type = NETWORK_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().childUpdate()) {
+                    // Masked by the child events (e.g. Removal)
+                    break;
+                }
+                type = NETWORK_UPDATED;
+                break;
+            case REMOVE:
+                type = NETWORK_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setNetworkKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener class to map listener map events to the TENODE events.
+     */
+    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:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by the parent event (e.g. Add)
+                    break;
+                }
+                type = TE_NODE_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().childUpdate() ||
+                        event.newValue().value().parentUpdate()) {
+                    // Masked by the child event (e.g. Removal) or parent event
+                    break;
+                }
+                type = TE_NODE_UPDATED;
+                break;
+            case REMOVE:
+                type = TE_NODE_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setTeNodeKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener class to map listener map events to the NETWORK NODE events.
+     */
+    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:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by the parent event (e.g. Add)
+                    break;
+                }
+                type = NODE_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().childUpdate() ||
+                        event.newValue().value().parentUpdate()) {
+                    // Masked by the child event (e.g. Removal) or parent event
+                    break;
+                }
+                type = NODE_UPDATED;
+                break;
+            case REMOVE:
+                type = NODE_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setNetworkNodeKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener class to map listener map events to the TELINK events.
+     */
+    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:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by the parent event (e.g. Add)
+                    break;
+                }
+                type = TE_LINK_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by parent event
+                    break;
+                }
+                type = TE_LINK_UPDATED;
+                break;
+            case REMOVE:
+                type = TE_LINK_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setTeLinkKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener class to map listener map events to the NETWORK LINK events.
+     */
+    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:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by the parent event (e.g. Add)
+                    break;
+                }
+                type = LINK_ADDED;
+                break;
+            case UPDATE:
+                if (event.newValue().value().parentUpdate()) {
+                    // Masked by the child event (e.g. Removal) or parent event
+                    break;
+                }
+                type = LINK_UPDATED;
+                break;
+            case REMOVE:
+                type = LINK_REMOVED;
+                break;
+            default:
+                log.error("Unsupported event type: {}", event.type());
+            }
+            if (type != null) {
+                TeTopologyMapEvent mapEvent = new TeTopologyMapEvent(type);
+                mapEvent.setNetworkLinkKey(event.key());
+                try {
+                    mapEventQueue.put(mapEvent);
+                } catch (InterruptedException e) {
+                    log.warn("Unable to queue event {} ", mapEvent, e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public TeTopologies teTopologies() {
+        Map<TeTopologyKey, TeTopology> teTopologies = Maps.newHashMap();
+        if (MapUtils.isNotEmpty(teTopologyMap)) {
+            for (TeTopologyKey key  : teTopologyMap.keySet()) {
+                teTopologies.put(key, teTopology(key));
+            }
+        }
+        return new DefaultTeTopologies(STORE_NAME, teTopologies);
+    }
+
+    private TeTopology teTopology(TeTopologyKey topologyId,
+                                  InternalTeTopology intTopology) {
+        if (intTopology == null) {
+            return null;
+        }
+        Map<Long, TeNode> teNodes = null;
+        if (CollectionUtils.isNotEmpty(intTopology.teNodeKeys())) {
+            teNodes = Maps.newHashMap();
+            for (TeNodeKey key : intTopology.teNodeKeys()) {
+                teNodes.put(key.teNodeId(), teNode(key));
+            }
+        }
+        Map<TeLinkTpKey, TeLink> teLinks = null;
+        if (CollectionUtils.isNotEmpty(intTopology.teLinkKeys())) {
+            teLinks = Maps.newHashMap();
+            for (TeLinkTpGlobalKey key : intTopology.teLinkKeys()) {
+                teLinks.put(key.teLinkTpKey(), teLink(key));
+            }
+        }
+        return new DefaultTeTopology(topologyId, teNodes, teLinks,
+                intTopology.teTopologyId(), intTopology.topologyData());
+    }
+
+    @Override
+    public TeTopology teTopology(TeTopologyKey topologyId) {
+        InternalTeTopology intTopology = teTopologyMap.get(topologyId);
+        return teTopology(topologyId, intTopology);
+    }
+
+    private void removeTopologyeMapEntrys(InternalTeTopology curTopology) {
+        // Remove TE nodes
+        if (CollectionUtils.isNotEmpty(curTopology.teNodeKeys())) {
+            for (TeNodeKey key : curTopology.teNodeKeys()) {
+                removeTeNode(key, true);
+            }
+        }
+        // Remove TE Links
+        if (CollectionUtils.isNotEmpty(curTopology.teLinkKeys())) {
+            for (TeLinkTpGlobalKey key : curTopology.teLinkKeys()) {
+                removeTeLink(key, true);
+            }
+        }
+    }
+
+    @Override
+    public void updateTeTopology(TeTopology teTopology) {
+        InternalTeTopology curTopology = teTopologyMap.get(teTopology.teTopologyId());
+        // Update TE nodes
+        List<NetworkNodeKey> nodeIds = null;
+        if (MapUtils.isNotEmpty(teTopology.teNodes())) {
+            nodeIds = Lists.newArrayList();
+            for (Map.Entry<Long, TeNode> entry : teTopology.teNodes().entrySet()) {
+                TeNodeKey teNodeKey = new TeNodeKey(teTopology.teTopologyId(), entry.getKey());
+                NetworkNodeKey nodeKey = TeMgrUtil.networkNodeKey(teNodeKey);
+                updateTeNode(teNodeKey, entry.getValue(), true, true, nodeKey);
+                nodeIds.add(nodeKey);
+            }
+        }
+        // Update TE links
+        List<NetworkLinkKey> linkIds = null;
+        if (MapUtils.isNotEmpty(teTopology.teLinks())) {
+            linkIds = Lists.newArrayList();
+            for (Map.Entry<TeLinkTpKey, TeLink> entry : teTopology.teLinks().entrySet()) {
+                TeLinkTpGlobalKey teLinkKey = new TeLinkTpGlobalKey(teTopology.teTopologyId(),
+                        entry.getKey());
+                NetworkLinkKey linkKey = TeMgrUtil.networkLinkKey(teLinkKey);
+                updateTeLink(teLinkKey, entry.getValue(), true, true, linkKey);
+                linkIds.add(linkKey);
+            }
+        }
+        // Finally Update teTopologyMap
+        InternalTeTopology newTopology = new InternalTeTopology(teTopology);
+        teTopologyMap.put(teTopology.teTopologyId(), newTopology);
+
+        if (curTopology == null) {
+            // New topology, update networkMap
+            InternalNetwork intNetwork = new InternalNetwork();
+            intNetwork.setServerProvided(false);
+            intNetwork.setTeTopologyKey(teTopology.teTopologyId());
+            intNetwork.setNodeIds(nodeIds);
+            intNetwork.setLinkIds(linkIds);
+            networkMap.put(teTopology.networkId(), intNetwork);
+        }
+    }
+
+    @Override
+    public void removeTeTopology(TeTopologyKey topologyId) {
+        // Remove it from teTopologyMap
+        InternalTeTopology topology = teTopologyMap.remove(topologyId);
+        if (topology != null) {
+            removeTopologyeMapEntrys(topology);
+            // Remove it from networkMap;
+            networkMap.remove(topology.topologyData().networkId());
+        }
+    }
+
+    @Override
+    public List<Network> networks() {
+        if (MapUtils.isEmpty(networkMap)) {
+            return null;
+        }
+        List<Network> networks = Lists.newArrayList();
+        for (KeyId networkId : networkMap.keySet()) {
+            networks.add(network(networkId));
+        }
+        return networks;
+    }
+
+    private Network network(KeyId networkId, InternalNetwork curNetwork) {
+        if (curNetwork == null) {
+            return null;
+        }
+        List<KeyId> supportingNetworkIds = curNetwork.supportingNetworkIds();
+        Map<KeyId, NetworkNode> nodes = null;
+        if (CollectionUtils.isNotEmpty(curNetwork.nodeIds())) {
+            nodes = Maps.newHashMap();
+            for (NetworkNodeKey key : curNetwork.nodeIds()) {
+                nodes.put(key.nodeId(), networkNode(key));
+            }
+        }
+        Map<KeyId, NetworkLink> links = null;
+        if (CollectionUtils.isNotEmpty(curNetwork.linkIds())) {
+            links = Maps.newHashMap();
+            for (NetworkLinkKey key : curNetwork.linkIds()) {
+                links.put(key.linkId(), networkLink(key));
+            }
+        }
+        TeTopologyId topologyId = null;
+        DeviceId ownerId = null;
+        if (curNetwork.teTopologyKey() != null &&
+                teTopologyMap.get(curNetwork.teTopologyKey()) != null) {
+            topologyId = new TeTopologyId(curNetwork.teTopologyKey().providerId(),
+                                          curNetwork.teTopologyKey().clientId(),
+                                          teTopologyMap
+                                                  .get(curNetwork
+                                                          .teTopologyKey())
+                                                  .teTopologyId());
+            ownerId = teTopologyMap.get(curNetwork.teTopologyKey())
+                    .topologyData().ownerId();
+
+        }
+        return new DefaultNetwork(networkId, supportingNetworkIds, nodes, links,
+                                  topologyId, curNetwork.serverProvided(), ownerId);
+    }
+
+    @Override
+    public Network network(KeyId networkId) {
+        InternalNetwork curNetwork = networkMap.get(networkId);
+        return network(networkId, curNetwork);
+    }
+
+    private void removeNetworkMapEntrys(InternalNetwork curNetwork, boolean teRemove) {
+        // Remove TE nodes
+        if (CollectionUtils.isNotEmpty(curNetwork.nodeIds())) {
+            for (NetworkNodeKey key : curNetwork.nodeIds()) {
+                removeNetworkNode(key, teRemove);
+            }
+        }
+        // Remove TE Links
+        if (CollectionUtils.isNotEmpty(curNetwork.linkIds())) {
+            for (NetworkLinkKey key : curNetwork.linkIds()) {
+                removeNetworkLink(key, teRemove);
+            }
+        }
+    }
+
+    private TeTopologyKey newTeTopologyKey(TeTopologyId teTopologyId) {
+        long idValue;
+        try {
+            idValue = Long.parseLong(teTopologyId.topologyId());
+        } catch (NumberFormatException e) {
+            // Can't get the long value from the string.
+            // Use an assigned id value from local id pool,
+            // Ideally id should be assigned per provider base.
+            idValue = nextTeTopologyId();
+        }
+        return new TeTopologyKey(teTopologyId.providerId(), teTopologyId.clientId(), idValue);
+    }
+
+    @Override
+    public void updateNetwork(Network network) {
+        InternalNetwork curNetwork = networkMap.get(network.networkId());
+        TeTopologyKey topoKey = null;
+        if (network.teTopologyId() != null) {
+            topoKey = newTeTopologyKey(network.teTopologyId());
+        }
+        // Update TE nodes
+        List<TeNodeKey> teNodeKeys = null;
+        if (MapUtils.isNotEmpty(network.nodes())) {
+            teNodeKeys = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkNode> entry : network.nodes().entrySet()) {
+                NetworkNodeKey nodeKey = new NetworkNodeKey(network.networkId(), entry.getKey());
+                TeNodeKey teNodeKey = null;
+                if (topoKey != null && entry.getValue().teNode() != null) {
+                    teNodeKey = new TeNodeKey(topoKey, entry.getValue().teNode().teNodeId());
+                }
+                updateNetworkNode(nodeKey, entry.getValue(), true, false, teNodeKey);
+                teNodeKeys.add(teNodeKey);
+            }
+        }
+        // Update TE links
+        List<TeLinkTpGlobalKey> teLinkKeys = null;
+        if (MapUtils.isNotEmpty(network.links())) {
+            teLinkKeys = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkLink> entry : network.links().entrySet()) {
+                NetworkLinkKey linkKey = new NetworkLinkKey(network.networkId(), entry.getKey());
+                TeLinkTpGlobalKey teLinkKey = null;
+                if (topoKey != null && entry.getValue().teLink() != null) {
+                    teLinkKey = new TeLinkTpGlobalKey(topoKey, entry.getValue().teLink().teLinkKey());
+                }
+                updateNetworkLink(linkKey, entry.getValue(), true, false, teLinkKey);
+                teLinkKeys.add(teLinkKey);
+            }
+        }
+
+        // New network, update TE Topology first
+        if (curNetwork == null) {
+            InternalTeTopology intTopo = new InternalTeTopology(network.teTopologyId().topologyId());
+            intTopo.setTeNodeKeys(teNodeKeys);
+            intTopo.setTeLinkKeys(teLinkKeys);
+            BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);
+            flags.set(TeTopology.BIT_LEARNT);
+            if (network.teTopologyId().clientId() == TeTopologyManager.DEFAULT_PROVIDER_ID) {
+                // Hard rule for now
+                flags.set(TeTopology.BIT_CUSTOMIZED);
+            }
+            CommonTopologyData common = new CommonTopologyData(network.networkId(),
+                    OptimizationType.NOT_OPTIMIZED, flags, network.ownerId());
+            intTopo.setTopologydata(common);
+            teTopologyMap.put(topoKey, intTopo);
+        }
+        // Finally Update networkMap
+        InternalNetwork newNetwork = new InternalNetwork(network);
+        newNetwork.setTeTopologyKey(topoKey);
+        networkMap.put(network.networkId(), newNetwork);
+    }
+
+    @Override
+    public void removeNetwork(KeyId networkId) {
+        // Remove it from networkMap
+        InternalNetwork network = networkMap.remove(networkId);
+        if (network != null && network.teTopologyKey() != null) {
+            removeNetworkMapEntrys(network, false);
+            teTopologyMap.remove(network.teTopologyKey());
+        }
+    }
+
+    private TeNode teNode(TeNodeKey nodeKey, InternalTeNode intNode) {
+        if (intNode == null) {
+            return null;
+        }
+        Map<Long, ConnectivityMatrix> connMatrices = null;
+        if (CollectionUtils.isNotEmpty(intNode.connMatrixKeys())) {
+            connMatrices = Maps.newHashMap();
+            for (ConnectivityMatrixKey key : intNode.connMatrixKeys()) {
+                connMatrices.put(key.entryId(), connMatrixMap.get(key));
+            }
+        }
+        List<Long> teLinkIds = null;
+        if (CollectionUtils.isNotEmpty(intNode.teLinkTpKeys())) {
+            teLinkIds = Lists.newArrayList();
+            for (TeLinkTpGlobalKey key : intNode.teLinkTpKeys()) {
+                teLinkIds = TeUtils.addListElement(teLinkIds, key.teLinkTpId());
+            }
+        }
+        List<Long> tps = null;
+        if (CollectionUtils.isNotEmpty(intNode.teTpKeys())) {
+            tps = Lists.newArrayList();
+            for (TeLinkTpGlobalKey key : intNode.teTpKeys()) {
+                tps = TeUtils.addListElement(tps, key.teLinkTpId());
+            }
+        }
+        Map<Long, TunnelTerminationPoint> ttps = null;
+        if (CollectionUtils.isNotEmpty(intNode.ttpKeys())) {
+            ttps = Maps.newHashMap();
+            for (TtpKey key : intNode.ttpKeys()) {
+                ttps.put(key.ttpId(), ttpMap.get(key));
+            }
+        }
+        return new DefaultTeNode(nodeKey.teNodeId(),
+                intNode.underlayTopologyKey(),
+                intNode.supportNodeKey(),
+                intNode.sourceTeNodeKey(),
+                intNode.teData(),
+                connMatrices, teLinkIds, ttps, tps);
+    }
+
+    @Override
+    public TeNode teNode(TeNodeKey nodeKey) {
+        InternalTeNode intNode = teNodeMap.get(nodeKey);
+        return teNode(nodeKey, intNode);
+    }
+
+    private void removeTeNodeMapEntrys(InternalTeNode intNode) {
+        // Remove connMatrixMap entries for the node
+        if (CollectionUtils.isNotEmpty(intNode.connMatrixKeys())) {
+            for (ConnectivityMatrixKey key : intNode.connMatrixKeys()) {
+                connMatrixMap.remove(key);
+            }
+        }
+        // Remove ttpMap entries for the node
+        if (CollectionUtils.isNotEmpty(intNode.ttpKeys())) {
+            for (TtpKey key : intNode.ttpKeys()) {
+                ttpMap.remove(key);
+            }
+        }
+    }
+
+    private void updateTeNode(TeNodeKey nodeKey, TeNode node, boolean parentUpdate,
+            boolean teNodeUpdate, NetworkNodeKey networkNodeKey) {
+        InternalTeTopology intTopo = teTopologyMap.get(nodeKey.teTopologyKey());
+        if (intTopo == null && !parentUpdate) {
+            log.error("TE Topology is not in dataStore for nodeUpdate {}", nodeKey);
+            return;
+        }
+        InternalTeNode curNode = teNodeMap.get(nodeKey);
+        // Update connMatrixMap
+        if (MapUtils.isNotEmpty(node.connectivityMatrices())) {
+            for (Map.Entry<Long, ConnectivityMatrix> entry : node.connectivityMatrices().entrySet()) {
+                connMatrixMap.put(new ConnectivityMatrixKey(nodeKey, entry.getKey()),
+                        entry.getValue());
+            }
+        }
+        // Update ttpMap
+        if (MapUtils.isNotEmpty(node.tunnelTerminationPoints())) {
+            for (Map.Entry<Long, TunnelTerminationPoint> entry : node.tunnelTerminationPoints().entrySet()) {
+                ttpMap.put(new TtpKey(nodeKey, entry.getKey()), entry.getValue());
+            }
+        }
+        // Update teNodeMap
+        InternalTeNode intNode = new InternalTeNode(nodeKey, node, networkNodeKey, parentUpdate);
+        teNodeMap.put(nodeKey, intNode);
+        if (curNode == null && !parentUpdate && intTopo != null) {
+            // Update InternalTeTopology
+           intTopo.setChildUpdate(true);
+           TeUtils.addListElement(intTopo.teNodeKeys(), nodeKey);
+        }
+        // Update networkNodeMap
+        if (teNodeUpdate) {
+            updateNetworkNode(networkNodeKey, networkNode(node), parentUpdate,
+                    teNodeUpdate, nodeKey);
+        }
+    }
+
+    private NetworkNode networkNode(TeNode node) {
+        KeyId nodeId = KeyId.keyId(Long.toString(node.teNodeId()));
+        List<NetworkNodeKey> supportingNodeIds = null;
+        if (node.supportingTeNodeId() != null) {
+            supportingNodeIds = Lists.newArrayList();
+            supportingNodeIds.add(new NetworkNodeKey(
+                    TeMgrUtil.toNetworkId((node.supportingTeNodeId().teTopologyKey())),
+                    KeyId.keyId(Long.toString(node.supportingTeNodeId().teNodeId()))));
+        }
+        Map<KeyId, TerminationPoint> tps = null;
+        if (node.teTerminationPointIds() != null) {
+            tps = Maps.newHashMap();
+            for (Long teTpId : node.teTerminationPointIds()) {
+                tps.put(KeyId.keyId(Long.toString(teTpId)),
+                        new DefaultTerminationPoint(KeyId.keyId(Long.toString(teTpId)),
+                                null, teTpId));
+            }
+        }
+        return new DefaultNetworkNode(nodeId, supportingNodeIds, node, tps);
+    }
+
+    @Override
+    public void updateTeNode(TeNodeKey nodeKey, TeNode node) {
+        updateTeNode(nodeKey, node, false, true, TeMgrUtil.networkNodeKey(nodeKey));
+    }
+
+    private void removeTeNode(TeNodeKey nodeKey, boolean teNodeRemove) {
+        // Remove it from InternalTeTopology first
+        InternalTeTopology intTopo = teTopologyMap.get(nodeKey.teTopologyKey());
+        if (intTopo != null && CollectionUtils.isNotEmpty(intTopo.teNodeKeys())) {
+            intTopo.setChildUpdate(true);
+            intTopo.teNodeKeys().remove(nodeKey);
+        }
+        // Then remove it from teNodeMap
+        InternalTeNode node = teNodeMap.remove(nodeKey);
+        removeTeNodeMapEntrys(node);
+        // Remove it from networkNodeMap
+        if (teNodeRemove && node != null) {
+            removeNetworkNode(node.networkNodeKey(), teNodeRemove);
+        }
+    }
+
+    @Override
+    public void removeTeNode(TeNodeKey nodeKey) {
+        removeTeNode(nodeKey, true);
+    }
+
+    private NetworkNode networkNode(NetworkNodeKey nodeKey, InternalNetworkNode intNode) {
+        if (intNode == null) {
+            return null;
+        }
+        Map<KeyId, TerminationPoint> tps = Maps.newHashMap();
+        for (KeyId tpId : intNode.tpIds()) {
+            tps.put(tpId, terminationPoint(
+                    new TerminationPointKey(nodeKey, tpId)));
+
+        }
+        return new DefaultNetworkNode(nodeKey.nodeId(), intNode.supportingNodeIds(),
+                teNode(intNode.teNodeKey()), tps);
+    }
+
+    @Override
+    public NetworkNode networkNode(NetworkNodeKey nodeKey) {
+        InternalNetworkNode intNode = networkNodeMap.get(nodeKey);
+        return networkNode(nodeKey, intNode);
+    }
+
+    private void updateNetworkNode(NetworkNodeKey nodeKey, NetworkNode node,
+            boolean parentUpdate, boolean teNodeUpdate, TeNodeKey teNodeKey) {
+        InternalNetwork intNework = null;
+        if (!parentUpdate) {
+            intNework = networkMap.get(nodeKey.networkId());
+            if (intNework == null) {
+                log.error("Network is not in dataStore for nodeUpdate {}", nodeKey);
+                return;
+            }
+        }
+
+        InternalNetworkNode exNode = networkNodeMap.get(nodeKey);
+        if (exNode != null && CollectionUtils.isNotEmpty(exNode.tpIds())) {
+            // Remove the TerminationPoints first
+            for (KeyId tpId : exNode.tpIds()) {
+                removeTerminationPoint(new TerminationPointKey(nodeKey, tpId));
+            }
+        }
+
+        if (MapUtils.isNotEmpty(node.terminationPoints())) {
+            // Update with new TerminationPoints
+            for (Map.Entry<KeyId, TerminationPoint> entry : node.terminationPoints().entrySet()) {
+                updateTerminationPoint(new TerminationPointKey(nodeKey, entry.getKey()),
+                        entry.getValue(), parentUpdate, teNodeKey);
+            }
+        }
+
+        // Update teNodeMap first
+        if (!teNodeUpdate && teNodeKey != null && node.teNode() != null) {
+            updateTeNode(teNodeKey, node.teNode(), parentUpdate, teNodeUpdate, nodeKey);
+        }
+        // Update networkNodeMap
+        InternalNetworkNode intNode = new InternalNetworkNode(node, parentUpdate);
+        intNode.setTeNodeKey(teNodeKey);
+        networkNodeMap.put(nodeKey, intNode);
+        if (exNode == null && !parentUpdate && intNework != null) {
+            // Update the InternalNetwork
+            intNework.setChildUpdate(true);
+            TeUtils.addListElement(intNework.nodeIds(), nodeKey);
+        }
+    }
+
+    @Override
+    public void updateNetworkNode(NetworkNodeKey nodeKey, NetworkNode node) {
+        TeNodeKey teNodeKey = null;
+        if (node.teNode() != null) {
+            teNodeKey = new TeNodeKey(networkMap.get(nodeKey.networkId()).teTopologyKey(),
+                                      node.teNode().teNodeId());
+        }
+        updateNetworkNode(nodeKey, node, false, false, teNodeKey);
+    }
+
+    private void removeNetworkNode(NetworkNodeKey nodeKey, boolean teNodeRemove) {
+        // Update the InternalNetwork
+        InternalNetwork intNework = networkMap.get(nodeKey.networkId());
+        if (intNework != null && CollectionUtils.isNotEmpty(intNework.nodeIds())) {
+            intNework.setChildUpdate(true);
+            intNework.nodeIds().remove(nodeKey.nodeId());
+        }
+        InternalNetworkNode intNode = networkNodeMap.remove(nodeKey);
+        if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
+            // Remove the TerminationPoints first
+            for (KeyId tpId : intNode.tpIds()) {
+                removeTerminationPoint(new TerminationPointKey(nodeKey, tpId));
+            }
+        }
+        if (!teNodeRemove && intNode != null) {
+            // Now remove it from teNodeMap
+            removeTeNode(intNode.teNodeKey(), teNodeRemove);
+        }
+    }
+
+    @Override
+    public void removeNetworkNode(NetworkNodeKey nodeKey) {
+        removeNetworkNode(nodeKey, false);
+    }
+
+    private TeLink teLink(TeLinkTpGlobalKey linkKey, InternalTeLink intLink) {
+        if (intLink == null) {
+            return null;
+        }
+        return new DefaultTeLink(linkKey.teLinkTpKey(),
+                intLink.peerTeLinkKey(),
+                intLink.underlayTopologyKey(),
+                intLink.supportingLinkKey(),
+                intLink.sourceTeLinkKey(),
+                intLink.teData());
+    }
+
+    @Override
+    public TeLink teLink(TeLinkTpGlobalKey linkKey) {
+        InternalTeLink intLink = teLinkMap.get(linkKey);
+        return teLink(linkKey, intLink);
+    }
+
+    private void updateTeLink(TeLinkTpGlobalKey linkKey, TeLink link,
+            boolean parentUpdate, boolean teLinkUpdate, NetworkLinkKey networkLinkKey) {
+        InternalTeTopology intTopo = teTopologyMap.get(linkKey.teTopologyKey());
+        if (intTopo == null && !parentUpdate) {
+            log.error("TE Topology is not in dataStore for linkUpdate {}", linkKey);
+            return;
+        }
+        InternalTeNode intNode = teNodeMap.get(linkKey.teNodeKey());
+        if (intNode == null && !parentUpdate) {
+            log.error("TE node is not in dataStore for linkUpdate {}", linkKey);
+            return;
+        }
+        InternalTeLink exLink = teLinkMap.get(linkKey);
+
+        // Update teLinkMap
+        InternalTeLink intLink = new InternalTeLink(link, parentUpdate);
+        intLink.setNetworkLinkKey(networkLinkKey);
+        teLinkMap.put(linkKey, intLink);
+        if (exLink == null && !parentUpdate) {
+            if (intTopo != null) {
+                // Update the InternalTeTopology
+                intTopo.setChildUpdate(true);
+                intTopo.setTeLinkKeys(TeUtils.addListElement(intTopo.teLinkKeys(), linkKey));
+            }
+            if (intNode != null) {
+                // Update the InternalNode
+                intNode.setChildUpdate(true);
+                intNode.setTeLinkTpKeys(TeUtils.addListElement(intNode.teLinkTpKeys(), linkKey));
+            }
+        }
+
+        // Update networkLinkMap
+        if (teLinkUpdate) {
+            updateNetworkLink(networkLinkKey, networkLink(link), parentUpdate,
+                    teLinkUpdate, linkKey);
+        }
+    }
+
+    private NetworkLink networkLink(TeLink link) {
+        KeyId linkId = TeMgrUtil.toNetworkLinkId(link.teLinkKey());
+        NodeTpKey source = null;
+        if (link.teLinkKey() != null) {
+            source = new NodeTpKey(KeyId.keyId(Long.toString(link.teLinkKey().teNodeId())),
+                                   KeyId.keyId(Long.toString(link.teLinkKey().teLinkTpId())));
+        }
+        NodeTpKey dest = null;
+        if (link.peerTeLinkKey() != null) {
+            dest = new NodeTpKey(KeyId.keyId(Long.toString(link.peerTeLinkKey().teNodeId())),
+                    KeyId.keyId(Long.toString(link.peerTeLinkKey().teLinkTpId())));
+        }
+        List<NetworkLinkKey> supportingLinkIds = null;
+        if (link.supportingTeLinkId() != null) {
+            supportingLinkIds = Lists.newArrayList();
+            supportingLinkIds.add(new NetworkLinkKey(
+                    TeMgrUtil.toNetworkId(link.supportingTeLinkId().teTopologyKey()),
+                    TeMgrUtil.toNetworkLinkId(link.supportingTeLinkId().teLinkTpKey())));
+        }
+        return new DefaultNetworkLink(linkId, source, dest, supportingLinkIds, link);
+    }
+
+    @Override
+    public void updateTeLink(TeLinkTpGlobalKey linkKey, TeLink link) {
+        updateTeLink(linkKey, link, false, true, TeMgrUtil.networkLinkKey(linkKey));
+    }
+
+    private void removeTeLink(TeLinkTpGlobalKey linkKey, boolean teLinkRemove) {
+        // Remove it from InternalTeTopology first
+        InternalTeTopology intTopo = teTopologyMap.get(linkKey.teTopologyKey());
+        if (intTopo != null && CollectionUtils.isNotEmpty(intTopo.teLinkKeys())) {
+           intTopo.setChildUpdate(true);
+           intTopo.teLinkKeys().remove(linkKey);
+        }
+        // Remove it from InternalTeNode
+        InternalTeNode intNode = teNodeMap.get(linkKey.teNodeKey());
+        if (intNode != null && CollectionUtils.isNotEmpty(intNode.teLinkTpKeys())) {
+            intNode.setChildUpdate(true);
+            intNode.teLinkTpKeys().remove(linkKey);
+        }
+        // Then remove it from teLinkMap
+        InternalTeLink link = teLinkMap.remove(linkKey);
+        if (teLinkRemove && link != null) {
+            // Remove it from networkLinkMap
+            removeNetworkLink(link.networkLinkKey(), teLinkRemove);
+        }
+     }
+
+    @Override
+    public void removeTeLink(TeLinkTpGlobalKey linkKey) {
+        removeTeLink(linkKey, true);
+    }
+
+    private NetworkLink networkLink(NetworkLinkKey linkKey, InternalNetworkLink intLink) {
+        if (intLink == null) {
+            return null;
+        }
+        return new DefaultNetworkLink(linkKey.linkId(), intLink.source(),
+                intLink.destination(), intLink.supportingLinkIds(), teLink(intLink.teLinkKey()));
+    }
+
+    @Override
+    public NetworkLink networkLink(NetworkLinkKey linkKey) {
+        InternalNetworkLink intLink = networkLinkMap.get(linkKey);
+        return networkLink(linkKey, intLink);
+    }
+
+    private void updateNetworkLink(NetworkLinkKey linkKey, NetworkLink link,
+            boolean parentUpdate, boolean teLinkUpdate, TeLinkTpGlobalKey teLinkKey) {
+        InternalNetwork intNework = null;
+        if (!parentUpdate) {
+            intNework = networkMap.get(linkKey.networkId());
+            if (intNework == null) {
+                log.error("Network is not in dataStore for linkUpdate {}", linkKey);
+                return;
+            }
+        }
+
+        InternalNetworkLink exLink = networkLinkMap.get(linkKey);
+
+        // Now update teLinkMap first
+        if (!teLinkUpdate && teLinkKey != null) {
+            updateTeLink(teLinkKey, link.teLink(), parentUpdate, teLinkUpdate, linkKey);
+        }
+        // Update networkLinkMap
+        InternalNetworkLink intLink = new InternalNetworkLink(link, parentUpdate);
+        intLink.setTeLinkKey(teLinkKey);
+        networkLinkMap.put(linkKey, intLink);
+        if (exLink == null && !parentUpdate && intNework != null) {
+            // Update the InternalNetwork
+            intNework.setChildUpdate(true);
+            TeUtils.addListElement(intNework.linkIds(), linkKey);
+        }
+    }
+
+    @Override
+    public void updateNetworkLink(NetworkLinkKey linkKey, NetworkLink link) {
+        TeLinkTpGlobalKey teLinkKey = null;
+        if (link.teLink() != null) {
+            teLinkKey = new TeLinkTpGlobalKey(networkMap.get(linkKey.networkId()).teTopologyKey(),
+                                              link.teLink().teLinkKey());
+        }
+
+        updateNetworkLink(linkKey, link, false, false, teLinkKey);
+    }
+
+    private void removeNetworkLink(NetworkLinkKey linkKey, boolean teLinkRemove) {
+        // Update the InternalNetwork
+        InternalNetwork intNework = networkMap.get(linkKey.networkId());
+        if (intNework != null && CollectionUtils.isNotEmpty(intNework.linkIds())) {
+            intNework.setChildUpdate(true);
+            intNework.linkIds().remove(linkKey.linkId());
+        }
+        // Remove it from networkLinkMap
+        InternalNetworkLink intLink = networkLinkMap.remove(linkKey);
+        if (!teLinkRemove && intLink != null && intLink.teLinkKey() != null) {
+            // Now remove it from teLinkMap
+            removeTeLink(intLink.teLinkKey(), teLinkRemove);
+        }
+    }
+
+    @Override
+    public void removeNetworkLink(NetworkLinkKey linkKey) {
+        removeNetworkLink(linkKey, false);
+    }
+
+    private TerminationPoint terminationPoint(TerminationPointKey tpKey) {
+        InternalTerminationPoint intTp = tpMap.get(tpKey);
+        if (intTp == null) {
+            return null;
+        }
+        return new DefaultTerminationPoint(tpKey.tpId(), intTp.supportingTpIds(),
+                intTp.teTpKey().teLinkTpId());
+    }
+
+    private void updateTerminationPoint(TerminationPointKey tpKey,
+            TerminationPoint tp, boolean parentUpdate, TeNodeKey teNodeKey) {
+        TeNodeKey myTeNodeKey;
+        InternalNetworkNode intNode = null;
+        if (!parentUpdate) {
+            intNode = networkNodeMap.get(tpKey.nodeId());
+            if (intNode == null) {
+                log.error(" node is not in dataStore for tp update {}", tpKey);
+                return;
+            }
+            myTeNodeKey = intNode.teNodeKey();
+        } else {
+            myTeNodeKey = teNodeKey;
+        }
+        TeLinkTpGlobalKey teTpKey = new TeLinkTpGlobalKey(myTeNodeKey, tp.teTpId());
+
+        boolean newTp = tpMap.get(tpKey) == null;
+        InternalTerminationPoint intTp = new InternalTerminationPoint(tp);
+        intTp.setTeTpKey(teTpKey);
+        tpMap.put(tpKey, intTp);
+        if (newTp) {
+            // Update tpKeyMap
+            tpKeyMap.put(teTpKey, tpKey);
+            if (!parentUpdate && intNode != null) {
+                // Update InternalNetworkNode
+                intNode.setChildUpdate(true);
+                intNode.setTpIds(TeUtils.addListElement(intNode.tpIds(), tpKey.tpId()));
+            }
+        }
+    }
+
+    @Override
+    public void updateTerminationPoint(TerminationPointKey tpKey,
+            TerminationPoint tp) {
+        updateTerminationPoint(tpKey, tp, false, null);
+    }
+
+    @Override
+    public void removeTerminationPoint(TerminationPointKey tpKey) {
+        // Update InternalNetworkNode
+        InternalNetworkNode intNode = networkNodeMap.get(tpKey.nodeId());
+        if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
+            intNode.setChildUpdate(true);
+            intNode.tpIds().remove(tpKey.tpId());
+        }
+        // Remove it from tpMap
+        InternalTerminationPoint tp = tpMap.remove(tpKey);
+        // Remove it from tpKeyMap
+        if (tp != null) {
+            tpKeyMap.remove(tp.teTpKey());
+        }
+    }
+
+    @Override
+    public TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId) {
+        return ttpMap.get(ttpId);
+    }
+
+    @Override
+    public long nextTeTopologyId() {
+        return nextTeTopologyId.getAndIncrement();
+    }
+
+    @Override
+    public long nextTeNodeId(TeTopologyKey topoKey) {
+        return teTopologyMap.get(topoKey).nextTeNodeId();
+    }
+
+    @Override
+    public void setNextTeNodeId(TeTopologyKey topoKey, long nextNodeId) {
+        teTopologyMap.get(topoKey).setNextTeNodeId(nextNodeId);
+    }
+
+    @Override
+    public KeyId networkId(TeTopologyKey teTopologyKey) {
+        return teTopologyMap.get(teTopologyKey).topologyData().networkId();
+    }
+
+    @Override
+    public NetworkNodeKey nodeKey(TeNodeKey teNodeKey) {
+        return teNodeMap.get(teNodeKey).networkNodeKey();
+    }
+
+    @Override
+    public NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey) {
+        return teLinkMap.get(teLinkKey).networkLinkKey();
+    }
+
+    @Override
+    public TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey) {
+        return tpKeyMap.get(teTpKey);
+    }
+
+    @Override
+    public void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue) {
+        mapEventQueue = queue;
+    }
+}
+
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetwork.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetwork.java
new file mode 100644
index 0000000..5aea01e
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetwork.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Network representation in store.
+ */
+public class InternalNetwork {
+    private TeTopologyKey teTopologyKey;
+    private List<KeyId> supportingNetworkIds;
+    private boolean serverProvided;
+    private List<NetworkNodeKey> nodeIds;
+    private List<NetworkLinkKey> linkIds;
+    private boolean childUpdate = false;
+
+    /**
+     * Creates an instance of InternalNetwork.
+     *
+     * @param network the Network object
+     */
+    public InternalNetwork(Network network) {
+        this.supportingNetworkIds = network
+                .supportingNetworkIds() == null ? null
+                                                : Lists.newArrayList(network
+                                                        .supportingNetworkIds());
+        this.serverProvided = network.isServerProvided();
+        // NetworkNodeKey
+        if (MapUtils.isNotEmpty(network.nodes())) {
+            this.nodeIds = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkNode> entry : network.nodes().entrySet()) {
+                this.nodeIds.add(new NetworkNodeKey(network.networkId(), entry.getKey()));
+            }
+        }
+        // NetworkLinkKey
+        if (MapUtils.isNotEmpty(network.links())) {
+            this.linkIds = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkLink> entry : network.links().entrySet()) {
+                this.linkIds.add(new NetworkLinkKey(network.networkId(), entry.getKey()));
+            }
+        }
+    }
+
+    /**
+     * Creates a default instance of InternalNetwork.
+     */
+    public InternalNetwork() {
+    }
+
+    /**
+     * Returns the supporting network Ids.
+     *
+     * @return the supportingNetworkIds
+     */
+    public List<KeyId> supportingNetworkIds() {
+        if (supportingNetworkIds == null) {
+            return null;
+        }
+        return ImmutableList.copyOf(supportingNetworkIds);
+    }
+
+    /**
+     * Returns if the network topology is provided by a server or is
+     * configured by a client.
+     *
+     * @return true if the network is provided by a server; false otherwise
+     */
+    public boolean serverProvided() {
+        return serverProvided;
+    }
+
+    /**
+     * @param serverProvided the serverProvided to set
+     */
+    public void setServerProvided(boolean serverProvided) {
+        this.serverProvided = serverProvided;
+    }
+
+    /**
+     * Returns the list of node Ids in the network.
+     *
+     * @return the nodeIds
+     */
+    public List<NetworkNodeKey> nodeIds() {
+        return nodeIds;
+    }
+
+    /**
+     * Returns the TE topology key for the network.
+     *
+     * @return the teTopologyKey
+     */
+    public TeTopologyKey teTopologyKey() {
+        return teTopologyKey;
+    }
+
+    /**
+     * Sets the TE topology key for the network.
+     *
+     * @param teTopologyKey the teTopologyKey to set
+     */
+    public void setTeTopologyKey(TeTopologyKey teTopologyKey) {
+        this.teTopologyKey = teTopologyKey;
+    }
+
+    /**
+     * Set the list of node Ids in the network.
+     *
+     * @param nodeIds the nodeIds to set
+     */
+    public void setNodeIds(List<NetworkNodeKey> nodeIds) {
+        this.nodeIds = nodeIds;
+    }
+
+    /**
+     * Returns the list of link Ids in the network.
+     *
+     * @return the linkIds
+     */
+    public List<NetworkLinkKey> linkIds() {
+        return linkIds;
+    }
+
+    /**
+     * Set the list of link Ids in the network.
+     *
+     * @param linkIds the linkIds to set
+     */
+    public void setLinkIds(List<NetworkLinkKey> linkIds) {
+        this.linkIds = linkIds;
+    }
+
+    /**
+     * Returns the flag if the data was updated by child change.
+     *
+     * @return value of childUpdate
+     */
+    public boolean childUpdate() {
+        return childUpdate;
+    }
+
+    /**
+     * Sets the flag if the data was updated by child change.
+     *
+     * @param childUpdate the childUpdate value to set
+     */
+    public void setChildUpdate(boolean childUpdate) {
+        this.childUpdate = childUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(teTopologyKey, nodeIds, linkIds,
+                supportingNetworkIds, serverProvided);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalNetwork) {
+            InternalNetwork that = (InternalNetwork) object;
+            return Objects.equal(this.teTopologyKey, that.teTopologyKey) &&
+                    Objects.equal(this.nodeIds, that.nodeIds) &&
+                    Objects.equal(this.linkIds, that.linkIds) &&
+                    Objects.equal(this.supportingNetworkIds, that.supportingNetworkIds) &&
+                    Objects.equal(this.serverProvided, that.serverProvided);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("teTopologyKey", teTopologyKey)
+                .add("nodeIds", nodeIds)
+                .add("linkIds", linkIds)
+                .add("supportingNetworkIds", supportingNetworkIds)
+                .add("serverProvided", serverProvided)
+                .add("childUpdate", childUpdate)
+                .toString();
+    }
+
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkLink.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkLink.java
new file mode 100644
index 0000000..e1f1fba
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkLink.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.NodeTpKey;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Network Link representation in store.
+ */
+public class InternalNetworkLink {
+    private NodeTpKey source;
+    private NodeTpKey destination;
+    private List<NetworkLinkKey> supportingLinkIds;
+    private TeLinkTpGlobalKey teLinkKey;
+    private boolean parentUpdate;
+
+    /**
+     * Creates an instance of InternalNetworkLink.
+     *
+     * @param link the network link
+     * @param parentUpdate the flag if the data is updated by parent
+     */
+    public InternalNetworkLink(NetworkLink link,  boolean parentUpdate) {
+        source = link.source();
+        destination = link.destination();
+        supportingLinkIds = link
+                .supportingLinkIds() == null ? null
+                                             : Lists.newArrayList(link
+                                                     .supportingLinkIds());
+        this.parentUpdate = parentUpdate;
+    }
+
+    /**
+     * Returns the link source termination point.
+     *
+     * @return source link termination point id
+     */
+    public NodeTpKey source() {
+        return source;
+    }
+
+    /**
+     * Returns the link destination termination point.
+     *
+     * @return destination link termination point id
+     */
+    public NodeTpKey destination() {
+        return destination;
+    }
+
+    /**
+     * Returns the supporting link ids.
+     *
+     * @return list of the ids of the supporting links
+     */
+    public List<NetworkLinkKey> supportingLinkIds() {
+        return supportingLinkIds == null ? null
+                                         : ImmutableList
+                                                 .copyOf(supportingLinkIds);
+    }
+
+    /**
+     * Returns the TE link key.
+     *
+     * @return the teLinkKey
+     */
+    public TeLinkTpGlobalKey teLinkKey() {
+        return teLinkKey;
+    }
+
+    /**
+     * Sets the TE link key.
+     *
+     * @param teLinkKey the teLinkKey to set
+     */
+    public void setTeLinkKey(TeLinkTpGlobalKey teLinkKey) {
+        this.teLinkKey = teLinkKey;
+    }
+
+    /**
+     * Returns the flag if the data was updated by parent change.
+     *
+     * @return value of parentUpdate
+     */
+    public boolean parentUpdate() {
+        return parentUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(source, destination, supportingLinkIds, teLinkKey);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalNetworkLink) {
+            InternalNetworkLink that = (InternalNetworkLink) object;
+            return Objects.equal(source, that.source)
+                    && Objects.equal(destination, that.destination)
+                    && Objects.equal(supportingLinkIds, that.supportingLinkIds)
+                    && Objects.equal(teLinkKey, that.teLinkKey);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("source", source)
+                .add("destination", destination)
+                .add("supportingLinkIds", supportingLinkIds)
+                .add("teLinkKey", teLinkKey)
+                .toString();
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkNode.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkNode.java
new file mode 100644
index 0000000..72b2e3c
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalNetworkNode.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Network Node representation in store.
+ */
+public class InternalNetworkNode {
+    private List<NetworkNodeKey> supportingNodeIds;
+    private List<KeyId> tpIds;
+    private TeNodeKey teNodeKey;
+    private boolean parentUpdate;
+    private boolean childUpdate;
+
+    /**
+     * Creates an instance of InternalNetworkNode.
+     *
+     * @param node the network node
+     * @param parentUpdate the flag if the data is updated by parent
+     */
+    public InternalNetworkNode(NetworkNode node,  boolean parentUpdate) {
+        supportingNodeIds = node
+                .supportingNodeIds() == null ? null
+                                             : Lists.newArrayList(node
+                                                     .supportingNodeIds());
+        if (MapUtils.isNotEmpty(node.terminationPoints())) {
+            tpIds = Lists.newArrayList();
+            for (Map.Entry<KeyId, TerminationPoint> entry : node
+                    .terminationPoints().entrySet()) {
+                tpIds.add(entry.getKey());
+            }
+        }
+        this.parentUpdate = parentUpdate;
+    }
+
+    /**
+     * Returns the list of supporting node Ids.
+     *
+     * @return the supporting nodeIds
+     */
+    public List<NetworkNodeKey> supportingNodeIds() {
+        return supportingNodeIds == null ? null
+                                         : ImmutableList
+                                                 .copyOf(supportingNodeIds);
+    }
+
+    /**
+     * Sets the list of supporting node Ids.
+     *
+     * @param supportingNodeIds the supportingNodeIds to set
+     */
+    public void setSupportingNodeIds(List<NetworkNodeKey> supportingNodeIds) {
+        this.supportingNodeIds = supportingNodeIds == null ? null
+                                                           : Lists.newArrayList(supportingNodeIds);
+    }
+
+    /**
+     * Returns the list of termination point Ids.
+     *
+     * @return the termination point Ids
+     */
+    public List<KeyId> tpIds() {
+        return tpIds;
+    }
+
+    /**
+     * Sets the list of termination point Ids.
+     *
+     * @param tpIds the tpIds to set
+     */
+    public void setTpIds(List<KeyId> tpIds) {
+        this.tpIds = tpIds;
+    }
+
+    /**
+     * Returns the TE Node key.
+     *
+     * @return the teNodeKey
+     */
+    public TeNodeKey teNodeKey() {
+        return teNodeKey;
+    }
+
+    /**
+     * Sets the TE Node key.
+     *
+     * @param teNodeKey the teNodeKey to set
+     */
+    public void setTeNodeKey(TeNodeKey teNodeKey) {
+        this.teNodeKey = teNodeKey;
+    }
+
+    /**
+     * Returns the flag if the data was updated by parent change.
+     *
+     * @return value of parentUpdate
+     */
+    public boolean parentUpdate() {
+        return parentUpdate;
+    }
+
+    /**
+     * Returns the flag if the data was updated by child change.
+     *
+     * @return value of childUpdate
+     */
+    public boolean childUpdate() {
+        return childUpdate;
+    }
+
+    /**
+     * Sets the flag if the data was updated by child change.
+     *
+     * @param childUpdate the childUpdate value to set
+     */
+    public void setChildUpdate(boolean childUpdate) {
+        this.childUpdate = childUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(supportingNodeIds, tpIds, teNodeKey);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalNetworkNode) {
+            InternalNetworkNode that = (InternalNetworkNode) object;
+            return Objects.equal(supportingNodeIds, that.supportingNodeIds)
+                    && Objects.equal(tpIds, that.tpIds)
+                    && Objects.equal(teNodeKey, that.teNodeKey);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("supportingNodeIds", supportingNodeIds)
+                .add("tpIds", tpIds)
+                .add("teNodeKey", teNodeKey)
+                .add("parentUpdate", parentUpdate)
+                .add("childUpdate", childUpdate)
+                .toString();
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeLink.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeLink.java
new file mode 100644
index 0000000..6274a4b
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeLink.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.CommonLinkData;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * The TE link representation in store.
+ */
+public class InternalTeLink {
+    private TeLinkTpKey peerTeLinkKey;
+    private TeTopologyKey underlayTopologyKey;
+    private TeLinkTpGlobalKey supportingLinkKey;
+    private TeLinkTpGlobalKey sourceTeLinkKey;
+    private CommonLinkData teData;
+    private NetworkLinkKey networkLinkKey;
+    private boolean parentUpdate;
+
+    /**
+     * Creates an instance of InternalLink.
+     *
+     * @param link the TE link
+     * @param parentUpdate indicator the TE node is updated by parent
+     */
+    public InternalTeLink(TeLink link, boolean parentUpdate) {
+        this.parentUpdate = parentUpdate;
+        // Peer link key
+        this.peerTeLinkKey = link.peerTeLinkKey();
+        // Underlay topology
+        this.underlayTopologyKey = link.underlayTeTopologyId();
+        // Supporting topology
+        this.supportingLinkKey = link.supportingTeLinkId();
+        // Source topology
+        this.sourceTeLinkKey = link.sourceTeLinkId();
+        // Common data
+        this.teData = new CommonLinkData(link);
+    }
+
+    /**
+     * Returns the bi-directional peer link key.
+     *
+     * @return the peerTeLinkKey
+     */
+    public TeLinkTpKey peerTeLinkKey() {
+        return peerTeLinkKey;
+    }
+
+    /**
+     * Sets the bi-directional peer link key.
+     *
+     * @param peerTeLinkKey the peerTeLinkKey to set
+     */
+    public void setPeerTeLinkKey(TeLinkTpKey peerTeLinkKey) {
+        this.peerTeLinkKey = peerTeLinkKey;
+    }
+
+    /**
+     * Returns the link underlay topology key.
+     *
+     * @return the underlayTopologyKey
+     */
+    public TeTopologyKey underlayTopologyKey() {
+        return underlayTopologyKey;
+    }
+
+    /**
+     * Sets the link underlay topology key.
+     *
+     * @param underlayTopologyKey the underlayTopologyKey to set
+     */
+    public void setUnderlayTopologyKey(TeTopologyKey underlayTopologyKey) {
+        this.underlayTopologyKey = underlayTopologyKey;
+    }
+
+    /**
+     * Returns the supporting link key.
+     *
+     * @return the supportingLinkKey
+     */
+    public TeLinkTpGlobalKey supportingLinkKey() {
+        return supportingLinkKey;
+    }
+
+    /**
+     * Sets the supporting link key.
+     *
+     * @param supportingLinkKey the supportingLinkKey to set
+     */
+    public void setSupportingLinkKey(TeLinkTpGlobalKey supportingLinkKey) {
+        this.supportingLinkKey = supportingLinkKey;
+    }
+
+    /**
+     * Returns the source link key.
+     *
+     * @return the sourceTeLinkKey
+     */
+    public TeLinkTpGlobalKey sourceTeLinkKey() {
+        return sourceTeLinkKey;
+    }
+
+    /**
+     * Sets the source link key.
+     *
+     * @param sourceTeLinkKey the sourceTeLinkKey to set
+     */
+    public void setSourceTeNodeKey(TeLinkTpGlobalKey sourceTeLinkKey) {
+        this.sourceTeLinkKey = sourceTeLinkKey;
+    }
+
+    /**
+     * Returns the link common data.
+     *
+     * @return the teData
+     */
+    public CommonLinkData teData() {
+        return teData;
+    }
+
+    /**
+     * Sets the link common data.
+     *
+     * @param teData the teData to set
+     */
+    public void setTeData(CommonLinkData teData) {
+        this.teData = teData;
+    }
+
+    /**
+     * Sets the network link key.
+     *
+     * @param networkLinkKey the networkLinkKey to set
+     */
+    public void setNetworkLinkKey(NetworkLinkKey networkLinkKey) {
+        this.networkLinkKey = networkLinkKey;
+    }
+
+    /**
+     * Returns the network link key.
+     *
+     * @return the networkLinkKey
+     */
+    public NetworkLinkKey networkLinkKey() {
+        return networkLinkKey;
+    }
+
+    /**
+     * Returns the indicator if the data was updated by parent.
+     *
+     * @return value of parentUpdate
+     */
+    public boolean parentUpdate() {
+        return parentUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(peerTeLinkKey, underlayTopologyKey,
+                supportingLinkKey, sourceTeLinkKey, teData, networkLinkKey);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalTeLink) {
+            InternalTeLink that = (InternalTeLink) object;
+            return Objects.equal(peerTeLinkKey, that.peerTeLinkKey)
+                    && Objects.equal(underlayTopologyKey,
+                                     that.underlayTopologyKey)
+                    && Objects.equal(supportingLinkKey, that.supportingLinkKey)
+                    && Objects.equal(sourceTeLinkKey, that.sourceTeLinkKey)
+                    && Objects.equal(networkLinkKey, that.networkLinkKey)
+                    && Objects.equal(teData, that.teData);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("peerTeLinkKey", peerTeLinkKey)
+                .add("underlayTopologyKey", underlayTopologyKey)
+                .add("supportingLinkKey", supportingLinkKey)
+                .add("sourceTeLinkKey", sourceTeLinkKey)
+                .add("teData", teData)
+                .add("networkLinkKey", networkLinkKey)
+                .add("parentUpdate", parentUpdate)
+                .toString();
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeNode.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeNode.java
new file mode 100644
index 0000000..03d47ff
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeNode.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.CommonNodeData;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrixKey;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+/**
+ * The Node representation in store.
+ */
+public class InternalTeNode {
+    private CommonNodeData teData;
+    private TeTopologyKey underlayTopologyKey;
+    private TeNodeKey supportNodeKey;
+    private TeNodeKey sourceTeNodeKey;
+    private List<ConnectivityMatrixKey> connMatrixKeys;
+    private List<TeLinkTpGlobalKey> teLinkTpKeys;
+    private List<TeLinkTpGlobalKey> teTpKeys;
+    private List<TtpKey> ttpKeys;
+    private NetworkNodeKey networkNodeKey;
+    private boolean parentUpdate;
+    private boolean childUpdate;
+
+    // Next available TE link Id egressing from the TE node.
+    private long nextTeLinkId;
+
+    /**
+     * Creates an instance of InternalTeNode.
+     *
+     * @param nodeKey the TE node key
+     * @param node the TE node
+     * @param networkNodeKey the network node key
+     * @param parentUpdate the flag if the data is updated by parent
+     */
+    public InternalTeNode(TeNodeKey nodeKey, TeNode node,
+           NetworkNodeKey networkNodeKey, boolean parentUpdate) {
+        this.networkNodeKey = networkNodeKey;
+        this.parentUpdate = parentUpdate;
+        // Underlay topology
+        this.underlayTopologyKey = node.underlayTeTopologyId();
+        // Supporting topology
+        this.supportNodeKey = node.supportingTeNodeId();
+        // Source topology
+        this.sourceTeNodeKey = node.sourceTeNodeId();
+        // Common data
+        this.teData = new CommonNodeData(node);
+        // Connectivity matrix
+        if (MapUtils.isNotEmpty(node.connectivityMatrices())) {
+            this.connMatrixKeys = Lists.newArrayList();
+            for (Map.Entry<Long, ConnectivityMatrix> entry : node.connectivityMatrices().entrySet()) {
+                this.connMatrixKeys.add(new ConnectivityMatrixKey(nodeKey, entry.getKey()));
+            }
+        }
+        // Tunnel termination point
+        if (MapUtils.isNotEmpty(node.tunnelTerminationPoints())) {
+            this.ttpKeys = Lists.newArrayList();
+            for (Map.Entry<Long, TunnelTerminationPoint> entry : node.tunnelTerminationPoints().entrySet()) {
+                this.ttpKeys.add(new TtpKey(nodeKey, entry.getKey()));
+            }
+        }
+        // teLink Keys
+        if (CollectionUtils.isNotEmpty(node.teLinkIds())) {
+            this.teLinkTpKeys = Lists.newArrayList();
+            for (Long linkId : node.teLinkIds()) {
+                this.teLinkTpKeys.add(new TeLinkTpGlobalKey(nodeKey, linkId));
+            }
+
+        }
+        // teTp Keys
+        if (CollectionUtils.isNotEmpty(node.teTerminationPointIds())) {
+            this.teTpKeys = Lists.newArrayList();
+            for (Long tpId : node.teTerminationPointIds()) {
+                this.teTpKeys.add(new TeLinkTpGlobalKey(nodeKey, tpId));
+            }
+        }
+    }
+
+    /**
+     * Returns the node common data.
+     *
+     * @return the teData
+     */
+    public CommonNodeData teData() {
+        return teData;
+    }
+
+    /**
+     * Sets the node common data.
+     *
+     * @param teData the teData to set
+     */
+    public void setTeData(CommonNodeData teData) {
+        this.teData = teData;
+    }
+
+    /**
+     * Returns the node underlay topology key.
+     *
+     * @return the underlayTopologyKey
+     */
+    public TeTopologyKey underlayTopologyKey() {
+        return underlayTopologyKey;
+    }
+
+    /**
+     * Sets the node underlay topology key.
+     *
+     * @param underlayTopologyKey the underlayTopologyKey to set
+     */
+    public void setUnderlayTopologyKey(TeTopologyKey underlayTopologyKey) {
+        this.underlayTopologyKey = underlayTopologyKey;
+    }
+
+    /**
+     * Returns the supporting node key.
+     *
+     * @return the supportNodeKey
+     */
+    public TeNodeKey supportNodeKey() {
+        return supportNodeKey;
+    }
+
+    /**
+     * Sets the supporting node key.
+     *
+     * @param supportNodeKey the supportNodeKey to set
+     */
+    public void setSupportNodeKey(TeNodeKey supportNodeKey) {
+        this.supportNodeKey = supportNodeKey;
+    }
+
+    /**
+     * Returns the source node key.
+     *
+     * @return the sourceTeNodeKey
+     */
+    public TeNodeKey sourceTeNodeKey() {
+        return sourceTeNodeKey;
+    }
+
+    /**
+     * Sets the source node key.
+     *
+     * @param sourceTeNodeKey the sourceTeNodeKey to set
+     */
+    public void setSourceTeNodeKey(TeNodeKey sourceTeNodeKey) {
+        this.sourceTeNodeKey = sourceTeNodeKey;
+    }
+
+    /**
+     * Returns the node connect matrix keys.
+     *
+     * @return the connMatrixKeys
+     */
+    public List<ConnectivityMatrixKey> connMatrixKeys() {
+        return connMatrixKeys;
+    }
+
+    /**
+     * Sets the node connect matrix keys.
+     *
+     * @param connMatrixKeys the connMatrixKeys to set
+     */
+    public void setConnMatrixKeys(List<ConnectivityMatrixKey> connMatrixKeys) {
+        this.connMatrixKeys = connMatrixKeys;
+    }
+
+    /**
+     * Returns the TE link Ids.
+     *
+     * @return the teLinkTpKeys
+     */
+    public List<TeLinkTpGlobalKey> teLinkTpKeys() {
+        return teLinkTpKeys;
+    }
+
+    /**
+     * Sets the TE link Ids from the node.
+     *
+     * @param teLinkTpKeys the teLinkTpKeys to set
+     */
+    public void setTeLinkTpKeys(List<TeLinkTpGlobalKey> teLinkTpKeys) {
+        this.teLinkTpKeys = teLinkTpKeys;
+    }
+
+    /**
+     * Returns the TE termitation point Ids.
+     *
+     * @return the teTpKeys
+     */
+    public List<TeLinkTpGlobalKey> teTpKeys() {
+        return teTpKeys;
+    }
+
+    /**
+     * Sets the TE termitation point Ids.
+     *
+     * @param teTpKeys the teTpKeys to set
+     */
+    public void setTeTpKeys(List<TeLinkTpGlobalKey> teTpKeys) {
+        this.teTpKeys = teTpKeys;
+    }
+
+    /**
+     * Returns the list of Tunnel Termination Point keys of the node.
+     *
+     * @return the ttpKeys
+     */
+    public List<TtpKey> ttpKeys() {
+        return ttpKeys;
+    }
+
+    /**
+     * Sets the list of Tunnel Termination Point keys.
+     *
+     * @param ttpKeys the ttpKeys to set
+     */
+    public void setTtpKeys(List<TtpKey> ttpKeys) {
+        this.ttpKeys = ttpKeys;
+    }
+
+    /**
+     * Returns the network node Key.
+     *
+     * @return the networkNodeKey
+     */
+    public NetworkNodeKey networkNodeKey() {
+        return networkNodeKey;
+    }
+
+    /**
+     * Returns the next available TE link id from the node.
+     *
+     * @return the nextTeLinkId
+     */
+    public long nextTeLinkId() {
+        return nextTeLinkId;
+    }
+
+    /**
+     * Sets the next available TE link id.
+     *
+     * @param nextTeLinkId the nextTeLinkId to set
+     */
+    public void setNextTeLinkId(long nextTeLinkId) {
+        this.nextTeLinkId = nextTeLinkId;
+    }
+
+    /**
+     * Returns the flag if the data was updated by parent change.
+     *
+     * @return value of parentUpdate
+     */
+    public boolean parentUpdate() {
+        return parentUpdate;
+    }
+
+    /**
+     * Returns the flag if the data was updated by child change.
+     *
+     * @return value of childUpdate
+     */
+    public boolean childUpdate() {
+        return childUpdate;
+    }
+
+    /**
+     * Sets the flag if the data was updated by child change.
+     *
+     * @param childUpdate the childUpdate value to set
+     */
+    public void setChildUpdate(boolean childUpdate) {
+        this.childUpdate = childUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(teData, underlayTopologyKey, supportNodeKey,
+                sourceTeNodeKey, connMatrixKeys, teLinkTpKeys, ttpKeys, networkNodeKey);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalTeNode) {
+            InternalTeNode that = (InternalTeNode) object;
+            return Objects.equal(teData, that.teData)
+                    && Objects.equal(underlayTopologyKey,
+                                     that.underlayTopologyKey)
+                    && Objects.equal(supportNodeKey, that.supportNodeKey)
+                    && Objects.equal(sourceTeNodeKey, that.sourceTeNodeKey)
+                    && Objects.equal(connMatrixKeys, that.connMatrixKeys)
+                    && Objects.equal(teLinkTpKeys, that.teLinkTpKeys)
+                    && Objects.equal(ttpKeys, that.ttpKeys)
+                    && Objects.equal(networkNodeKey, that.networkNodeKey);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("teData", teData)
+                .add("underlayTopologyKey", underlayTopologyKey)
+                .add("supportNodeKey", supportNodeKey)
+                .add("sourceTeNodeKey", sourceTeNodeKey)
+                .add("connMatrixKeys", connMatrixKeys)
+                .add("teLinkTpKeys", teLinkTpKeys)
+                .add("ttpKeys", ttpKeys)
+                .add("nextTeLinkId", nextTeLinkId)
+                .add("networkNodeKey", networkNodeKey)
+                .add("parentUpdate", parentUpdate)
+                .add("childUpdate", childUpdate)
+                .toString();
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeTopology.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeTopology.java
new file mode 100644
index 0000000..ed71d47
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTeTopology.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import static org.onosproject.tetopology.management.api.TeConstants.NIL_LONG_VALUE;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
+import org.onosproject.tetopology.management.api.CommonTopologyData;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+/**
+ * TE topology representation in store.
+ */
+public class InternalTeTopology {
+    private String teTopologyId;
+    private List<TeNodeKey> teNodeKeys;
+    private List<TeLinkTpGlobalKey> teLinkKeys;
+    private CommonTopologyData topologyData;
+    private long nextTeNodeId = NIL_LONG_VALUE;
+    private boolean childUpdate;
+
+    /**
+     * Creates an instance of InternalTeTopology.
+     *
+     * @param teTopology the TE Topology object
+     */
+    public InternalTeTopology(TeTopology teTopology) {
+        this.teTopologyId = teTopology.teTopologyIdStringValue();
+        this.topologyData = new CommonTopologyData(teTopology);
+        // teNodeKeys
+        if (MapUtils.isNotEmpty(teTopology.teNodes())) {
+            this.teNodeKeys = Lists.newArrayList();
+            for (Map.Entry<Long, TeNode> entry : teTopology.teNodes().entrySet()) {
+                this.teNodeKeys.add(new TeNodeKey(teTopology.teTopologyId(), entry.getKey()));
+            }
+        }
+        // teLink Keys
+        if (MapUtils.isNotEmpty(teTopology.teLinks())) {
+            this.teLinkKeys = Lists.newArrayList();
+            for (Map.Entry<TeLinkTpKey, TeLink> entry : teTopology.teLinks().entrySet()) {
+                this.teLinkKeys.add(new TeLinkTpGlobalKey(teTopology.teTopologyId(), entry.getKey()));
+            }
+        }
+    }
+
+    /**
+     * Creates a default instance of InternalNetwork.
+     *
+     * @param teTopologyId string value of id
+     */
+    public InternalTeTopology(String teTopologyId) {
+        this.teTopologyId = teTopologyId;
+    }
+
+    /**
+     * Returns the TE Topology Id string value.
+     *
+     * @return the teTopologyId
+     */
+    public String teTopologyId() {
+        return teTopologyId;
+    }
+
+    /**
+     * Returns the list of TE node keys in the topology.
+     *
+     * @return the teNodeKeys
+     */
+    public List<TeNodeKey> teNodeKeys() {
+        return teNodeKeys;
+    }
+
+    /**
+     * Sets the list of TE node keys.
+     *
+     * @param teNodeKeys the teNodeKeys to set
+     */
+    public void setTeNodeKeys(List<TeNodeKey> teNodeKeys) {
+        this.teNodeKeys = teNodeKeys;
+    }
+
+    /**
+     * Returns the list of TE link keys in the topology.
+     *
+     * @return the teLinkKeys
+     */
+    public List<TeLinkTpGlobalKey> teLinkKeys() {
+        return teLinkKeys;
+    }
+
+    /**
+     * Sets the list of TE link keys.
+     *
+     * @param teLinkKeys the teLinkKeys to set
+     */
+    public void setTeLinkKeys(List<TeLinkTpGlobalKey> teLinkKeys) {
+        this.teLinkKeys = teLinkKeys;
+    }
+
+    /**
+     * Returns the common TE topology data.
+     *
+     * @return the topology data
+     */
+    public CommonTopologyData topologyData() {
+        return topologyData;
+    }
+
+    /**
+     * Sets the common TE topology data.
+     *
+     * @param topologyData the topologyData to set
+     */
+    public void setTopologydata(CommonTopologyData topologyData) {
+        this.topologyData = topologyData;
+    }
+
+    /**
+     * Returns the next available TE node Id.
+     *
+     * @return the next TE nodeId
+     */
+    public long nextTeNodeId() {
+        return nextTeNodeId;
+    }
+
+    /**
+     * Sets the next available TE node Id.
+     *
+     * @param nextTeNodeId the nextTeNodeId to set
+     */
+    public void setNextTeNodeId(long nextTeNodeId) {
+        this.nextTeNodeId = nextTeNodeId;
+    }
+
+    /**
+     * Returns the flag if the data was updated by child change.
+     *
+     * @return value of childUpdate
+     */
+    public boolean childUpdate() {
+        return childUpdate;
+    }
+
+    /**
+     * Sets the flag if the data was updated by child change.
+     *
+     * @param childUpdate the childUpdate value to set
+     */
+    public void setChildUpdate(boolean childUpdate) {
+        this.childUpdate = childUpdate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(teTopologyId, teNodeKeys, teLinkKeys,
+                topologyData);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalTeTopology) {
+            InternalTeTopology that = (InternalTeTopology) object;
+            return Objects.equal(teTopologyId, that.teTopologyId)
+                    && Objects.equal(teNodeKeys, that.teNodeKeys)
+                    && Objects.equal(teLinkKeys, that.teLinkKeys)
+                    && Objects.equal(topologyData, that.topologyData);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("teTopologyId", teTopologyId)
+                .add("teNodeKeys", teNodeKeys)
+                .add("teLinkKeys", teLinkKeys)
+                .add("topologyData", topologyData)
+                .add("nextTeNodeId", nextTeNodeId)
+                .add("childUpdate", childUpdate)
+                .toString();
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTerminationPoint.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTerminationPoint.java
new file mode 100644
index 0000000..c40df38
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/InternalTerminationPoint.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * The TerminationPoint representation in store.
+ */
+public class InternalTerminationPoint {
+    private TeLinkTpGlobalKey teTpKey;
+    private List<TerminationPointKey> supportingTpIds;
+
+    /**
+     * Creates an instance of InternalTerminationPoint.
+     *
+     * @param tp the termination point
+     */
+    public InternalTerminationPoint(TerminationPoint tp) {
+        this.supportingTpIds = tp
+                .supportingTpIds() == null ? null
+                                           : Lists.newArrayList(tp
+                                                   .supportingTpIds());
+    }
+
+    /**
+     * Returns the TE termination point key.
+     *
+     * @return the teTpKey
+    */
+    public TeLinkTpGlobalKey teTpKey() {
+        return teTpKey;
+    }
+
+    /**
+     * Returns the supporting termination point Ids.
+     *
+     * @return the supportingTpIds
+     */
+    public List<TerminationPointKey> supportingTpIds() {
+        return supportingTpIds == null ? null
+                                       : ImmutableList.copyOf(supportingTpIds);
+    }
+
+    /**
+     * Sets the TE termination point key.
+     *
+     * @param teTpKey the teTpKey to set
+     */
+    public void setTeTpKey(TeLinkTpGlobalKey teTpKey) {
+        this.teTpKey = teTpKey;
+    }
+
+    /**
+     * Sets the supporting termination point Ids.
+     *
+     * @param supportingTpIds the supportingTpIds to set
+     */
+    public void setSupportingTpIds(List<TerminationPointKey> supportingTpIds) {
+        this.supportingTpIds = supportingTpIds == null ? null
+                                                       : Lists.newArrayList(supportingTpIds);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(supportingTpIds, teTpKey);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof InternalTerminationPoint) {
+            InternalTerminationPoint that = (InternalTerminationPoint) object;
+            return Objects.equal(supportingTpIds, that.supportingTpIds)
+                    && Objects.equal(teTpKey, that.teTpKey);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("supportingTpIds", supportingTpIds)
+                .add("teTpKey", teTpKey)
+                .toString();
+    }
+
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeMgrUtil.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeMgrUtil.java
new file mode 100644
index 0000000..5781663
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeMgrUtil.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.NodeTpKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * TE Topology Manager utility functions.
+ */
+public final class TeMgrUtil {
+    private static final String TENODE_ID = "teNodeId/";
+    private static final String TELINK_ID = "/teLinkId/";
+    private static final String PROVIDER_ID = "providerId/";
+    private static final String CLIENT_ID = "/clientId/";
+    private static final String TOPOLOGY_ID = "/topologyId/";
+
+    // no instantiation
+    private TeMgrUtil() {
+    }
+
+    /**
+     * Returns the network link id for a TE link local key.
+     *
+     * @param  key TE link local key
+     * @return value of network link id
+     */
+    public static KeyId toNetworkLinkId(TeLinkTpKey key) {
+        return KeyId.keyId(new StringBuilder()
+                .append(TENODE_ID)
+                .append(Ip4Address.valueOf((int) key.teNodeId()).toString())
+                .append(TELINK_ID)
+                .append(key.teLinkTpId()).toString());
+    }
+
+    /**
+     * Returns the network id for a TE topology id.
+     *
+     * @param  teTopologyId TE topology id
+     * @return value of network id
+     */
+    public static KeyId toNetworkId(TeTopologyId teTopologyId) {
+        return KeyId.keyId(new StringBuilder()
+                .append(PROVIDER_ID)
+                .append(teTopologyId.providerId())
+                .append(CLIENT_ID)
+                .append(teTopologyId.clientId())
+                .append(TOPOLOGY_ID)
+                .append(teTopologyId.topologyId()).toString());
+    }
+
+    /**
+     * Returns the network id for a TE topology key.
+     *
+     * @param  teTopologyKey TE topology key
+     * @return value of network id
+     */
+    public static KeyId toNetworkId(TeTopologyKey teTopologyKey) {
+        return KeyId.keyId(new StringBuilder()
+                .append(PROVIDER_ID)
+                .append(teTopologyKey.providerId())
+                .append(CLIENT_ID)
+                .append(teTopologyKey.clientId())
+                .append(TOPOLOGY_ID)
+                .append(teTopologyKey.topologyId()).toString());
+    }
+
+    /**
+     * Returns the network node key for a TE node global key.
+     *
+     * @param  teNodeKey TE node global key
+     * @return value of network node key
+     */
+    public static NetworkNodeKey networkNodeKey(TeNodeKey teNodeKey) {
+        return new NetworkNodeKey(toNetworkId(teNodeKey.teTopologyKey()),
+                                  KeyId.keyId(Long.toString(teNodeKey.teNodeId())));
+    }
+
+    /**
+     * Returns the network link key for a TE link global key.
+     *
+     * @param  teLinkKey TE link global key
+     * @return value of network link key
+     */
+    public static NetworkLinkKey networkLinkKey(TeLinkTpGlobalKey teLinkKey) {
+        return new NetworkLinkKey(toNetworkId(teLinkKey.teTopologyKey()),
+                                  toNetworkLinkId(teLinkKey.teLinkTpKey()));
+    }
+
+    /**
+     * Returns the TE topology id for a TE topology.
+     *
+     * @param  teTopology an instance of TE topology
+     * @return value of TE topology id
+     */
+    public static TeTopologyId teTopologyId(TeTopology teTopology) {
+        return new TeTopologyId(teTopology.teTopologyId().providerId(),
+                                teTopology.teTopologyId().clientId(),
+                                teTopology.teTopologyIdStringValue());
+    }
+
+    /**
+     * Returns a default instance of termination point for a TE termination point id.
+     *
+     * @param  teTpId TE termination point id
+     * @return an instance of termination point
+     */
+    private static TerminationPoint tpBuilder(long teTpId) {
+        return new DefaultTerminationPoint(KeyId.keyId(Long.toString(teTpId)), null, teTpId);
+    }
+
+    /**
+     * Returns an instance of network node for a TE node.
+     *
+     * @param id     value of the network node id
+     * @param teNode value of TE node
+     * @return an instance of network node
+     */
+    public static NetworkNode nodeBuilder(KeyId id, TeNode teNode) {
+        List<NetworkNodeKey> supportingNodeIds = null;
+        if (teNode.supportingTeNodeId() != null) {
+            supportingNodeIds = Lists.newArrayList(networkNodeKey(teNode.supportingTeNodeId()));
+        }
+        Map<KeyId, TerminationPoint> tps = Maps.newConcurrentMap();
+        for (Long teTpid : teNode.teTerminationPointIds()) {
+            tps.put(KeyId.keyId(Long.toString(teTpid)), tpBuilder(teTpid));
+        }
+        return new DefaultNetworkNode(id, supportingNodeIds, teNode, tps);
+    }
+
+    /**
+     * Returns the network node termination point key for a TE link end point key.
+     *
+     * @param  teLinkKey TE link end point key
+     * @return value of network node termination point key
+     */
+    public static NodeTpKey nodeTpKey(TeLinkTpKey teLinkKey) {
+        return new NodeTpKey(KeyId.keyId(Long.toString(teLinkKey.teNodeId())),
+                             KeyId.keyId(Long.toString(teLinkKey.teLinkTpId())));
+    }
+
+    /**
+     * Returns an instance of network link for a TE link.
+     *
+     * @param id     value of the network link id
+     * @param teLink value of TE link
+     * @return an instance of network link
+     */
+    public static NetworkLink linkBuilder(KeyId id, TeLink teLink) {
+        NodeTpKey source = nodeTpKey(teLink.teLinkKey());
+        NodeTpKey destination = null;
+        if (teLink.peerTeLinkKey() != null) {
+            destination = nodeTpKey(teLink.peerTeLinkKey());
+        }
+        List<NetworkLinkKey> supportingLinkIds = null;
+        if (teLink.supportingTeLinkId() != null) {
+            supportingLinkIds = Lists.newArrayList(networkLinkKey(teLink.supportingTeLinkId()));
+        }
+        return new DefaultNetworkLink(id, source, destination, supportingLinkIds, teLink);
+    }
+
+    /**
+     * Returns an instance of network for a TE topology.
+     *
+     * @param  teTopology value of TE topology
+     * @return an instance of network
+     */
+    public static Network networkBuilder(TeTopology teTopology) {
+        KeyId networkId = TeMgrUtil.toNetworkId(teTopology.teTopologyId());
+        TeTopologyId topologyId = teTopologyId(teTopology);
+        Map<KeyId, NetworkNode> nodes = null;
+        if (MapUtils.isNotEmpty(teTopology.teNodes())) {
+            nodes = Maps.newHashMap();
+            for (TeNode tenode : teTopology.teNodes().values()) {
+                KeyId key = KeyId.keyId(Long.toString(tenode.teNodeId()));
+                nodes.put(key, nodeBuilder(key, tenode));
+            }
+        }
+        Map<KeyId, NetworkLink> links = null;
+        if (MapUtils.isNotEmpty(teTopology.teLinks())) {
+            links = Maps.newHashMap();
+            for (TeLink telink : teTopology.teLinks().values()) {
+                KeyId key = TeMgrUtil.toNetworkLinkId(telink.teLinkKey());
+                links.put(key, linkBuilder(key, telink));
+
+            }
+        }
+        return new DefaultNetwork(networkId, null, nodes, links,
+                                  topologyId, false, teTopology.ownerId());
+    }
+
+}
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
new file mode 100644
index 0000000..ae2fc0e
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyConfig.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import org.onlab.packet.Ip4Address;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.net.config.Config;
+
+/**
+ * Configuration for TE Topology parameters.
+ */
+public class TeTopologyConfig extends Config<ApplicationId>  {
+    private static final String CONFIG_VALUE_ERROR = "Error parsing config value";
+    private static final String PROVIDER_ID = "provider-id";
+    private static final String TENODE_ID_START = "tenode-id-start";
+    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
+      */
+    public long providerId() throws ConfigException {
+        try {
+            return object.path(PROVIDER_ID).asLong();
+        } catch (IllegalArgumentException e) {
+            throw new ConfigException(CONFIG_VALUE_ERROR, e);
+        }
+    }
+
+    /**
+     * 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);
+      }
+  }
+
+}
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
new file mode 100644
index 0000000..aeb1fbe
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
@@ -0,0 +1,902 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_REMOVED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_UPDATED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_REMOVED;
+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 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;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.app.ApplicationException;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.LinkProviderRegistry;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.provider.AbstractListenerProviderRegistry;
+import org.onosproject.net.provider.AbstractProviderService;
+import org.onosproject.tetopology.management.api.CommonTopologyData;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.DefaultNetworks;
+import org.onosproject.tetopology.management.api.DefaultTeTopologies;
+import org.onosproject.tetopology.management.api.DefaultTeTopology;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.Networks;
+import org.onosproject.tetopology.management.api.OptimizationType;
+import org.onosproject.tetopology.management.api.TeConstants;
+import org.onosproject.tetopology.management.api.TeTopologies;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.TeTopologyListener;
+import org.onosproject.tetopology.management.api.TeTopologyProvider;
+import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
+import org.onosproject.tetopology.management.api.TeTopologyProviderService;
+import org.onosproject.tetopology.management.api.TeTopologyService;
+import org.onosproject.tetopology.management.api.link.CommonLinkData;
+import org.onosproject.tetopology.management.api.link.DefaultTeLink;
+import org.onosproject.tetopology.management.api.link.ExternalLink;
+import org.onosproject.tetopology.management.api.link.LinkBandwidth;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkEventSubject;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkEventSubject;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.link.TePathAttributes;
+import org.onosproject.tetopology.management.api.link.UnderlayPath;
+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.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeEventSubject;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeEventSubject;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Implementation of the topology management service.
+ */
+@Component(immediate = true)
+@Service
+public class TeTopologyManager
+    extends AbstractListenerProviderRegistry<TeTopologyEvent, TeTopologyListener,
+                                             TeTopologyProvider, TeTopologyProviderService>
+    implements TeTopologyService, TeTopologyProviderRegistry {
+    private static final String APP_NAME = "org.onosproject.tetopology";
+    public static final long DEFAULT_PROVIDER_ID = 0x0a0a0a0aL;
+    private static final long DEFAULT_CLIENT_ID = 0x00L;
+    private long providerId = DEFAULT_PROVIDER_ID;
+    private static final int MAX_THREADS = 1;
+
+    private static final Ip4Address DEFAULT_TENODE_ID_START = Ip4Address.valueOf("1.1.1.1");
+    private static final Ip4Address DEFAULT_TENODE_ID_END = Ip4Address.valueOf("250.250.250.250");
+    private Ip4Address teNodeIpStart = DEFAULT_TENODE_ID_START;
+    private Ip4Address teNodeIpEnd = DEFAULT_TENODE_ID_END;
+    private long nextTeNodeId = teNodeIpStart.toInt();
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigRegistry cfgService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceProviderRegistry deviceProviderRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkProviderRegistry linkProviderRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    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,
+                    "teTopologyCfg",
+                    false) {
+        @Override
+        public TeTopologyConfig createConfig() {
+            return new TeTopologyConfig();
+        }
+    };
+    private final NetworkConfigListener cfgLister = new InternalConfigListener();
+    private ApplicationId appId;
+    // The topology merged in MDSC
+    private TeTopology mergedTopology = null;
+    private TeTopologyKey mergedTopologyKey;
+    private Network mergedNetwork = null;
+    // Track new TE node id by its source TE node key
+    private Map<TeNodeKey, Long> sourceNewTeNodeIdMap = Maps.newHashMap();
+    // Track the external link keys by the plugId
+    private Map<Long, LinkKeyPair> externalLinkMap = Maps.newHashMap();
+    private ExecutorService executor;
+
+    /**
+     * Activation helper function.
+     */
+    public void activateBasics() {
+        store.setDelegate(delegate);
+        store.setMapEventQueue(mapEventQueue);
+        eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry);
+    }
+
+    /**
+     * Deactivation helper function.
+     */
+    public void deactivateBasics() {
+        store.unsetDelegate(delegate);
+        eventDispatcher.removeSink(TeTopologyEvent.class);
+    }
+
+    @Activate
+    public void activate() {
+        activateBasics();
+        appId = coreService.registerApplication(APP_NAME);
+        cfgService.registerConfigFactory(factory);
+        executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/tetopology", "build-%d", log));
+
+        cfgService.addListener(cfgLister);
+        executor.execute(new TopologyMergerTask());
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        deactivateBasics();
+        externalLinkMap.clear();
+        cfgService.removeListener(cfgLister);
+        cfgService.unregisterConfigFactory(factory);
+        executor.shutdownNow();
+        executor = null;
+        eventQueue.clear();
+        log.info("Stopped");
+    }
+
+    @Override
+    protected TeTopologyProviderService createProviderService(TeTopologyProvider provider) {
+        return new InternalTopologyProviderService(provider);
+    }
+
+    private class InternalTopologyProviderService
+                      extends AbstractProviderService<TeTopologyProvider>
+                      implements TeTopologyProviderService {
+
+        protected InternalTopologyProviderService(TeTopologyProvider provider) {
+            super(provider);
+        }
+
+        @Override
+        public void networkUpdated(Network network) {
+            store.updateNetwork(network);
+        }
+
+        @Override
+        public void networkRemoved(KeyId networkId) {
+            store.removeNetwork(networkId);
+        }
+
+        @Override
+        public void linkUpdated(NetworkLinkKey linkKey, NetworkLink link) {
+            store.updateNetworkLink(linkKey, link);
+        }
+
+        @Override
+        public void linkRemoved(NetworkLinkKey linkKey) {
+            store.removeNetworkLink(linkKey);
+        }
+
+        @Override
+        public void nodeUpdated(NetworkNodeKey nodeKey, NetworkNode node) {
+            store.updateNetworkNode(nodeKey, node);
+        }
+
+        @Override
+        public void nodeRemoved(NetworkNodeKey nodeKey) {
+            store.removeNetworkNode(nodeKey);
+        }
+
+        @Override
+        public void terminationPointUpdated(TerminationPointKey terminationPointKey,
+                TerminationPoint terminationPoint) {
+            store.updateTerminationPoint(terminationPointKey, terminationPoint);
+        }
+
+        @Override
+        public void terminationPointRemoved(TerminationPointKey terminationPointKey) {
+            store.removeTerminationPoint(terminationPointKey);
+        }
+    }
+
+    private boolean isCustomizedLearnedTopology(TeTopologyKey key) {
+        if (store.teTopology(key).flags().get(TeTopology.BIT_CUSTOMIZED) &&
+                store.teTopology(key).flags().get(TeTopology.BIT_LEARNT)) {
+            return true;
+        }
+        return false;
+    }
+
+    // Task for merge the learned topology.
+    private class TopologyMergerTask implements Runnable {
+
+        public TopologyMergerTask() {
+        }
+
+        @Override
+        public void run() {
+            try {
+                TeTopologyMapEvent event;
+                while ((event = mapEventQueue.take()) != null) {
+                    switch (event.type()) {
+                    case TE_TOPOLOGY_ADDED:
+                    case TE_TOPOLOGY_UPDATED:
+                        TeTopology teTopology = store.teTopology(event.teTopologyKey());
+                        post(new TeTopologyEvent(event.type(), teTopology));
+                        if (event.type() == TE_TOPOLOGY_ADDED &&
+                                teTopology.flags().get(TeTopology.BIT_CUSTOMIZED) &&
+                                teTopology.flags().get(TeTopology.BIT_LEARNT)) {
+                            mergeTopology(teTopology);
+                        }
+                        break;
+                    case TE_TOPOLOGY_REMOVED:
+                        post(new TeTopologyEvent(TE_TOPOLOGY_REMOVED,
+                                                 new DefaultTeTopology(event.teTopologyKey(),
+                                                                      null, null, null, null)));
+                        break;
+                    case TE_NODE_ADDED:
+                    case TE_NODE_UPDATED:
+                        TeNode teNode = store.teNode(event.teNodeKey());
+                        post(new TeTopologyEvent(event.type(),
+                                                 new TeNodeEventSubject(event.teNodeKey(), teNode)));
+                        if (isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
+                            updateSourceTeNode(mergedTopology.teNodes(),
+                                               event.teNodeKey().teTopologyKey(), teNode, true);
+                        }
+                        break;
+                    case TE_NODE_REMOVED:
+                        post(new TeTopologyEvent(TE_NODE_REMOVED,
+                                                 new TeNodeEventSubject(event.teNodeKey(), null)));
+                        if (isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
+                            removeSourceTeNode(mergedTopology.teNodes(), event.teNodeKey(), true);
+                        }
+                        break;
+                    case TE_LINK_ADDED:
+                    case TE_LINK_UPDATED:
+                        TeLink teLink = store.teLink(event.teLinkKey());
+                        post(new TeTopologyEvent(event.type(),
+                                                 new TeLinkEventSubject(event.teLinkKey(), teLink)));
+                        if (isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
+                            Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
+                            updateSourceTeLink(teLinks, event.teLinkKey().teTopologyKey(), teLink, true);
+                            updateMergedTopology(mergedTopology.teNodes(), teLinks);
+                        }
+                        break;
+                    case TE_LINK_REMOVED:
+                        post(new TeTopologyEvent(TE_LINK_REMOVED,
+                                                 new TeLinkEventSubject(event.teLinkKey(), null)));
+                        if (isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
+                            Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
+                            removeSourceTeLink(teLinks, event.teLinkKey(), true);
+                            updateMergedTopology(mergedTopology.teNodes(), teLinks);
+                        }
+                        break;
+                    case NETWORK_ADDED:
+                    case NETWORK_UPDATED:
+                        Network network = store.network(event.networkKey());
+                        post(new TeTopologyEvent(event.type(), network));
+                        break;
+                    case NETWORK_REMOVED:
+                        post(new TeTopologyEvent(NETWORK_REMOVED,
+                                                 new DefaultNetwork(event.networkKey(),
+                                                                    null, null, null, null, false, null)));
+                        break;
+                    case NODE_ADDED:
+                    case NODE_UPDATED:
+                        NetworkNode node = store.networkNode(event.networkNodeKey());
+                        post(new TeTopologyEvent(event.type(),
+                                                 new NetworkNodeEventSubject(event.networkNodeKey(), node)));
+                        break;
+                    case NODE_REMOVED:
+                        post(new TeTopologyEvent(NODE_REMOVED,
+                                                 new NetworkNodeEventSubject(event.networkNodeKey(), null)));
+                        break;
+                    case LINK_ADDED:
+                    case LINK_UPDATED:
+                        NetworkLink link = store.networkLink(event.networkLinkKey());
+                        post(new TeTopologyEvent(event.type(),
+                                                 new NetworkLinkEventSubject(event.networkLinkKey(), link)));
+                        break;
+                    case LINK_REMOVED:
+                        post(new TeTopologyEvent(LINK_REMOVED,
+                                                 new NetworkLinkEventSubject(event.networkLinkKey(), null)));
+                        break;
+                    default:
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                log.warn("TopologyMergerTask is interrupted");
+            } catch (Exception e) {
+                log.warn("Unable to merge topology", e);
+            }
+        }
+    }
+
+    private void removeSourceTeNode(Map<Long, TeNode> teNodes,
+                                    TeNodeKey srcNodeKey, boolean postEvent) {
+       Long mergedTeNodeId = sourceNewTeNodeIdMap.remove(srcNodeKey);
+       if (mergedTeNodeId == null) {
+           return;
+       }
+       if (teNodes.remove(mergedTeNodeId) != null && postEvent) {
+           post(new TeTopologyEvent(TE_NODE_REMOVED,
+                                    new TeNodeEventSubject(
+                                            new TeNodeKey(mergedTopologyKey,
+                                                          mergedTeNodeId),
+                                            null)));
+       }
+    }
+
+    private void updateSourceTeNode(Map<Long, TeNode> teNodes, TeTopologyKey srcTopoKey,
+                                    TeNode srcNode, boolean postEvent) {
+        TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey, srcNode.teNodeId());
+        Long mergedTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeId);
+        boolean addNode = false;
+        if (mergedTeNodeId == null) {
+            // New node
+            addNode = true;
+            mergedTeNodeId = nextTeNodeId;
+            nextTeNodeId++;
+            if (nextTeNodeId >= teNodeIpEnd.toInt()) {
+                nextTeNodeId = teNodeIpStart.toInt();
+                log.warn("TE node Id is wrapped back");
+            }
+            sourceNewTeNodeIdMap.put(sourceTeNodeId, mergedTeNodeId);
+        }
+        TeTopologyKey underlayTopologyId = null; // No underlay
+        TeNodeKey supportTeNodeId = null; // No supporting
+
+        CommonNodeData common = new CommonNodeData(srcNode.name(), srcNode.adminStatus(),
+                                                   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();
+        List<Long> teTpIds = srcNode.teTerminationPointIds(); // No change
+        DefaultTeNode newNode = new DefaultTeNode(mergedTeNodeId, underlayTopologyId,
+                supportTeNodeId, sourceTeNodeId, common, connMatrices, teLinkIds,
+                ttps, teTpIds);
+        teNodes.put(mergedTeNodeId, newNode);
+        if (postEvent) {
+            //Post event for the TE node in the merged topology
+            TeNodeKey globalKey = new TeNodeKey(mergedTopologyKey, mergedTeNodeId);
+            post(new TeTopologyEvent(addNode ? TE_NODE_ADDED : TE_NODE_UPDATED,
+                                     new TeNodeEventSubject(globalKey, newNode)));
+            post(new TeTopologyEvent(addNode ? NODE_ADDED : NODE_UPDATED,
+                                     new NetworkNodeEventSubject(TeMgrUtil.networkNodeKey(globalKey),
+                                             TeMgrUtil.nodeBuilder(
+                                                     KeyId.keyId(Long.toString(newNode.teNodeId())),
+                                                     newNode))));
+        }
+    }
+
+    // Merge TE nodes
+    private void mergeNodes(Map<Long, TeNode> nodes, TeTopology topology) {
+
+        if (!MapUtils.isEmpty(topology.teNodes())) {
+            for (Map.Entry<Long, TeNode> entry : topology.teNodes().entrySet()) {
+                updateSourceTeNode(nodes, topology.teTopologyId(), entry.getValue(),
+                                   mergedTopology != null);
+            }
+        }
+    }
+
+    // Returns a new TeLink based on an existing TeLink with new attributes
+    private TeLink updateTeLink(TeLinkTpKey newKey, TeLinkTpKey peerTeLinkKey,
+            TeTopologyKey underlayTopologyId, TeLinkTpGlobalKey supportTeLinkId,
+            TeLinkTpGlobalKey sourceTeLinkId, ExternalLink externalLink,
+            TeLink exLink) {
+        UnderlayPath underlayPath = new UnderlayPath(exLink.primaryPath(),
+                exLink.backupPaths(), exLink.tunnelProtectionType(),
+                exLink.sourceTtpId(), exLink.destinationTtpId(),
+                exLink.teTunnelId()
+                );
+        TePathAttributes teAttributes = new TePathAttributes(exLink.cost(),
+                exLink.delay(), exLink.srlgs());
+        LinkBandwidth bandwidth = new LinkBandwidth(exLink.maxBandwidth(),
+                                                    exLink.availBandwidth(),
+                                                    exLink.maxAvailLspBandwidth(),
+                                                    exLink.minAvailLspBandwidth(),
+                                                    exLink.oduResource());
+        CommonLinkData common = new CommonLinkData(exLink.adminStatus(), exLink.opStatus(),
+                exLink.flags(), exLink.switchingLayer(), exLink.encodingLayer(),
+                externalLink, underlayPath, teAttributes,
+                exLink.administrativeGroup(), exLink.interLayerLocks(),
+                bandwidth);
+        return new DefaultTeLink(newKey, peerTeLinkKey, underlayTopologyId,
+                supportTeLinkId, sourceTeLinkId, common);
+    }
+
+    private class LinkKeyPair {
+        private TeLinkTpKey firstKey;
+        private TeLinkTpKey secondKey;
+
+        public LinkKeyPair(TeLinkTpKey firstKey) {
+            this.firstKey = firstKey;
+        }
+
+        public TeLinkTpKey firstKey() {
+            return firstKey;
+        }
+
+        public void setFirstKey(TeLinkTpKey firstKey) {
+            this.firstKey = firstKey;
+        }
+
+        public TeLinkTpKey secondKey() {
+            return secondKey;
+        }
+
+        public void setSecondKey(TeLinkTpKey secondKey) {
+            this.secondKey = secondKey;
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                    .add("firstKey", firstKey)
+                    .add("secondKey", secondKey)
+                    .toString();
+        }
+    }
+
+    private void removeSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeLinkTpGlobalKey teLinkKey,
+                                    boolean postEvent) {
+        TeNodeKey sourceTeNodeKey = teLinkKey.teNodeKey();
+        Long newTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeKey);
+        if (newTeNodeId == null) {
+            return;
+        }
+        TeLinkTpKey newLinkKey = new TeLinkTpKey(newTeNodeId, teLinkKey.teLinkTpId());
+        TeLink teLink = teLinks.remove(newLinkKey);
+        if (teLink == null) {
+            return;
+        }
+        //Post event
+        if (postEvent) {
+            post(new TeTopologyEvent(TE_LINK_REMOVED,
+                                     new TeLinkEventSubject(
+                                             new TeLinkTpGlobalKey(mergedTopologyKey,
+                                                                   newLinkKey),
+                                             null)));
+        }
+
+        if (teLink.externalLink() != null && teLink.externalLink().plugId() != null) {
+            // Update the LinkKeyPair in externalLinkMap
+            LinkKeyPair pair = externalLinkMap.get(teLink.externalLink().plugId());
+            if (pair != null && pair.firstKey() != null &&
+                    pair.firstKey().equals(newLinkKey)) {
+                pair.setFirstKey(null);
+            } else if (pair != null && pair.secondKey() != null &&
+                    pair.secondKey().equals(newLinkKey)) {
+                pair.setSecondKey(null);
+            }
+            if (pair != null && pair.firstKey() == null &&
+                    pair.secondKey() == null) {
+                externalLinkMap.remove(teLink.externalLink().plugId());
+            }
+        }
+        TeLinkTpKey peerTeLinkKey = teLink.peerTeLinkKey();
+        if (peerTeLinkKey != null) {
+            // Update peerLink's peerTeLinkKey to null
+            TeLink peerLink = teLinks.get(peerTeLinkKey);
+            if (peerLink == null) {
+                return;
+            }
+            TeLink newPeerLink = updateTeLink(peerTeLinkKey, null,
+                                       peerLink.underlayTeTopologyId(), peerLink.supportingTeLinkId(),
+                                       peerLink.sourceTeLinkId(), peerLink.externalLink(), peerLink);
+            teLinks.put(peerTeLinkKey, newPeerLink);
+            if (postEvent) {
+                post(new TeTopologyEvent(TE_LINK_UPDATED,
+                                         new TeLinkEventSubject(
+                                                 new TeLinkTpGlobalKey(mergedTopologyKey,
+                                                                       peerTeLinkKey),
+                                                 newPeerLink)));
+            }
+        }
+    }
+
+    private void updateSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeTopologyKey srcTopoKey,
+                                    TeLink srcLink, boolean postEvent) {
+        TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey,
+                                                 srcLink.teLinkKey().teNodeId());
+        TeLinkTpKey newKey = new TeLinkTpKey(
+                sourceNewTeNodeIdMap.get(sourceTeNodeId),
+                srcLink.teLinkKey().teLinkTpId());
+        TeLinkTpKey peerTeLinkKey = null;
+        if (srcLink.peerTeLinkKey() != null) {
+            TeNodeKey sourcePeerNode = new TeNodeKey(srcTopoKey,
+                                                     srcLink.peerTeLinkKey().teNodeId());
+            peerTeLinkKey = new TeLinkTpKey(
+                    sourceNewTeNodeIdMap.get(sourcePeerNode),
+                    srcLink.peerTeLinkKey().teLinkTpId());
+        }
+
+        if (srcLink.externalLink() != null &&
+                srcLink.externalLink().plugId() != null) {
+            // externalLinkKey doesn't have topology Id.
+            // using plugId for now
+            LinkKeyPair pair = externalLinkMap.get(srcLink.externalLink().plugId());
+            if (pair != null) {
+                if (pair.firstKey() == null) {
+                    peerTeLinkKey = pair.secondKey;
+                    pair.setFirstKey(newKey);
+                } else {
+                    peerTeLinkKey = pair.firstKey;
+                    pair.setSecondKey(newKey);
+                }
+
+                TeLink peerLink = teLinks.get(peerTeLinkKey);
+                if (peerLink != null) {
+                    // Update peer Link with local link key
+                    TeLink newPeerLink = updateTeLink(peerTeLinkKey, newKey,
+                                                      peerLink.underlayTeTopologyId(),
+                                                      peerLink.supportingTeLinkId(),
+                                                      peerLink.sourceTeLinkId(),
+                                                      peerLink.externalLink(), peerLink);
+                    teLinks.put(peerTeLinkKey, newPeerLink);
+                    if (postEvent) {
+                        post(new TeTopologyEvent(TE_LINK_UPDATED,
+                                                 new TeLinkEventSubject(
+                                                         new TeLinkTpGlobalKey(mergedTopologyKey,
+                                                                               peerTeLinkKey),
+                                                         newPeerLink)));
+                    }
+
+               }
+            } else {
+                // Store it in the map
+                externalLinkMap.put(srcLink.externalLink().plugId(), new LinkKeyPair(newKey));
+            }
+        }
+
+        TeTopologyKey underlayTopologyId = null; // No underlay
+        TeLinkTpGlobalKey supportTeLinkId = null; // No support
+        // Source link for the new updated link
+        TeLinkTpGlobalKey sourceTeLinkId = new TeLinkTpGlobalKey(srcTopoKey, srcLink.teLinkKey());
+        TeLink updatedLink = updateTeLink(newKey, peerTeLinkKey, underlayTopologyId,
+                                      supportTeLinkId, sourceTeLinkId,
+                                      srcLink.externalLink(), srcLink);
+        TeLinkTpGlobalKey newGlobalKey = new TeLinkTpGlobalKey(mergedTopologyKey, newKey);
+        boolean newLink = teLinks.get(newGlobalKey) == null ? true : false;
+        teLinks.put(newKey, updatedLink);
+        if (postEvent) {
+            //Post event
+            post(new TeTopologyEvent(newLink ? TE_LINK_ADDED : TE_LINK_UPDATED,
+                                     new TeLinkEventSubject(newGlobalKey, updatedLink)));
+            post(new TeTopologyEvent(newLink ? LINK_ADDED : LINK_UPDATED,
+                                     new NetworkLinkEventSubject(TeMgrUtil.networkLinkKey(newGlobalKey),
+                                             TeMgrUtil.linkBuilder(TeMgrUtil.toNetworkLinkId(
+                                                                          updatedLink.teLinkKey()),
+                                                                   updatedLink))));
+        }
+    }
+
+    // Merge TE links
+    private void mergeLinks(Map<TeLinkTpKey, TeLink> teLinks, TeTopology topology) {
+        if (!MapUtils.isEmpty(topology.teLinks())) {
+            for (Map.Entry<TeLinkTpKey, TeLink> entry : topology.teLinks().entrySet()) {
+                TeLink srcLink = entry.getValue();
+                updateSourceTeLink(teLinks, topology.teTopologyId(), srcLink,
+                                   mergedTopology != null);
+            }
+        }
+    }
+
+    // Update the merged topology with new TE nodes and links
+    private void updateMergedTopology(Map<Long, TeNode> teNodes, Map<TeLinkTpKey, TeLink> teLinks) {
+        boolean newTopology = mergedTopology == null;
+        BitSet flags = newTopology ? new BitSet(TeConstants.FLAG_MAX_BITS) : mergedTopology.flags();
+        flags.set(TeTopology.BIT_MERGED);
+        CommonTopologyData commonData  = new CommonTopologyData(newTopology ?
+                                                                TeMgrUtil.toNetworkId(mergedTopologyKey) :
+                                                                mergedTopology.networkId(),
+                                                                OptimizationType.NOT_OPTIMIZED,
+                                                                flags, DeviceId.deviceId("localHost"));
+        mergedTopology = new DefaultTeTopology(mergedTopologyKey, teNodes, teLinks,
+                                               Long.toString(mergedTopologyKey.topologyId()), commonData);
+        mergedNetwork = TeMgrUtil.networkBuilder(mergedTopology);
+        log.info("Nodes# {}, Links# {}", mergedTopology.teNodes().size(), mergedTopology.teLinks().size());
+    }
+
+    // Merge the new learned topology
+    private void mergeTopology(TeTopology topology) {
+        boolean newTopology = mergedTopology == null;
+        mergedTopologyKey = newTopology ?
+                            new TeTopologyKey(providerId, DEFAULT_CLIENT_ID,
+                                              store.nextTeTopologyId()) :
+                            mergedTopology.teTopologyId();
+
+        Map<Long, TeNode> teNodes = newTopology || mergedTopology.teNodes() == null ?
+                Maps.newHashMap() : Maps.newHashMap(mergedTopology.teNodes());
+        mergeNodes(teNodes, topology);
+        Map<TeLinkTpKey, TeLink> teLinks = newTopology || mergedTopology.teLinks() == null ?
+                Maps.newHashMap() : Maps.newHashMap(mergedTopology.teLinks());
+        mergeLinks(teLinks, topology);
+        updateMergedTopology(teNodes, teLinks);
+        log.info("mergedTopology {}", mergedTopology);
+
+        if (newTopology) {
+            // Post events for the merged network topology;
+            post(new TeTopologyEvent(TE_TOPOLOGY_ADDED, mergedTopology));
+            post(new TeTopologyEvent(NETWORK_ADDED, mergedNetwork));
+        }
+    }
+
+    private TeTopologyKey newTeTopologyKey(TeTopology teTopology) {
+        TeTopologyKey key = teTopology.teTopologyId();
+        if (key == null || teTopology.teTopologyIdStringValue() == null) {
+            log.error("Ignoring the non-TE topology");
+            throw new ApplicationException("Missing TE topology ID");
+        }
+        // Get the topologyId numeric value
+        long idValue = key.topologyId();
+        if (idValue == TeConstants.NIL_LONG_VALUE) {
+            if (teTopology.teTopologyIdStringValue() != null) {
+                try {
+                    idValue = Long.parseLong(teTopology.teTopologyIdStringValue());
+                } catch (NumberFormatException e) {
+                    // Can't get the long value from the string.
+                    // Use an assigned id value from local id pool,
+                    idValue = store.nextTeTopologyId();
+                }
+                return new TeTopologyKey(key.providerId(), key.clientId(), idValue);
+            }
+        }
+        return null;
+    }
+
+    private class InternalConfigListener implements NetworkConfigListener {
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+            try {
+                providerId = cfgService.getConfig(appId, TeTopologyConfig.class)
+                                       .providerId();
+                teNodeIpStart = cfgService.getConfig(appId, TeTopologyConfig.class)
+                                          .teNodeIpStart();
+                teNodeIpEnd = cfgService.getConfig(appId, TeTopologyConfig.class)
+                                        .teNodeIpEnd();
+                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);
+        }
+    }
+
+    @Override
+    public TeTopologies teTopologies() {
+        Map<TeTopologyKey, TeTopology> map;
+        if (MapUtils.isNotEmpty(store.teTopologies().teTopologies())) {
+            map = Maps.newHashMap(store.teTopologies().teTopologies());
+        } else {
+            map = Maps.newHashMap();
+        }
+        if (mergedTopology != null) {
+            map.put(mergedTopologyKey, mergedTopology);
+        }
+        return new DefaultTeTopologies(store.teTopologies().name(), map);
+    }
+
+    @Override
+    public TeTopology teTopology(TeTopologyKey topologyId) {
+        if (mergedTopology != null &&
+                topologyId.equals(mergedTopologyKey)) {
+            return mergedTopology;
+        }
+        return store.teTopology(topologyId);
+    }
+
+    @Override
+    public TeTopology mergedTopology() {
+        return mergedTopology;
+    }
+
+    @Override
+    public void updateTeTopology(TeTopology teTopology) {
+        TeTopologyKey newKey = null;
+        try {
+            newKey = newTeTopologyKey(teTopology);
+        } catch (ApplicationException e) {
+            log.error("Ignoring the non-TE topology");
+            return;
+        }
+
+        // TE topology is updated here from other APP or NBI, the flag
+        // BIT_CUSTOMIZED or BIT_MERGED should be set.
+        BitSet flags = teTopology.flags();
+        if (flags == null ||
+                !(flags.get(TeTopology.BIT_CUSTOMIZED) ||
+                  flags.get(TeTopology.BIT_MERGED))) {
+            log.error("TE topology flags {} are not set properly", flags);
+            return;
+        }
+
+        if (newKey != null) {
+            DefaultTeTopology newTopology = new DefaultTeTopology(
+                    newKey == null ? teTopology.teTopologyId() : newKey,
+                    teTopology.teNodes(), teTopology.teLinks(),
+                    teTopology.teTopologyIdStringValue(), new CommonTopologyData(teTopology));
+            // Update with new data
+            store.updateTeTopology(newTopology);
+        } else {
+            store.updateTeTopology(teTopology);
+        }
+    }
+
+    @Override
+    public void removeTeTopology(TeTopologyKey topologyId) {
+        store.removeTeTopology(topologyId);
+    }
+
+    @Override
+    public Networks networks() {
+        List<Network> networks;
+        if (CollectionUtils.isNotEmpty(store.networks())) {
+            networks = Lists.newArrayList(store.networks());
+        } else {
+            networks = Lists.newArrayList();
+        }
+        if (mergedNetwork != null) {
+            networks.add(mergedNetwork);
+        }
+        return new DefaultNetworks(networks);
+    }
+
+    @Override
+    public Network network(KeyId networkId) {
+        if (mergedNetwork != null &&
+                mergedNetwork.networkId().equals(networkId)) {
+            return mergedNetwork;
+        }
+        return store.network(networkId);
+    }
+
+    @Override
+    public void updateNetwork(Network network) {
+        // TODO: This will be implemented if required.
+    }
+
+    @Override
+    public void removeNetwork(KeyId networkId) {
+        // TODO: This will be implemented if required.
+    }
+
+    @Override
+    public TeNode teNode(TeNodeKey nodeId) {
+        if (nodeId.teTopologyKey().equals(mergedTopologyKey)) {
+            return mergedTopology.teNode(nodeId.teNodeId());
+        }
+        return store.teNode(nodeId);
+    }
+
+    @Override
+    public TeLink teLink(TeLinkTpGlobalKey linkId) {
+        if (linkId.teTopologyKey().equals(mergedTopologyKey)) {
+            return mergedTopology.teLink(linkId.teLinkTpKey());
+        }
+        return store.teLink(linkId);
+    }
+
+    @Override
+    public TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId) {
+        if (ttpId.teTopologyKey().equals(mergedTopologyKey)) {
+            return mergedTopology.teNode(ttpId.teNodeId())
+                    .tunnelTerminationPoint(ttpId.ttpId());
+        }
+        return store.tunnelTerminationPoint(ttpId);
+    }
+
+    @Override
+    public KeyId networkId(TeTopologyKey teTopologyKey) {
+        return store.networkId(teTopologyKey);
+    }
+
+    @Override
+    public NetworkNodeKey nodeKey(TeNodeKey teNodeKey) {
+        return store.nodeKey(teNodeKey);
+    }
+
+    @Override
+    public NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey) {
+        return store.linkKey(teLinkKey);
+    }
+
+    @Override
+    public TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey) {
+        return store.terminationPointKey(teTpKey);
+    }
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyMapEvent.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyMapEvent.java
new file mode 100644
index 0000000..a88ab51
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyMapEvent.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.TeTopologyEvent.Type;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+
+import com.google.common.base.MoreObjects;
+
+public class TeTopologyMapEvent {
+    private final Type type;
+    private TeTopologyKey teTopologyKey;
+    private TeNodeKey teNodeKey;
+    private TeLinkTpGlobalKey teLinkKey;
+    private KeyId networkKey;
+    private NetworkNodeKey networkNodeKey;
+    private NetworkLinkKey networkLinkKey;
+
+    /**
+     * Creates an instance of TeTopologyMapEvent.
+     *
+     * @param type the map event type
+     */
+    public TeTopologyMapEvent(Type type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns the map event type.
+     *
+     * @return the type
+     */
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Returns the TE topology key of the event.
+     *
+     * @return the teTopologyKey
+     */
+    public TeTopologyKey teTopologyKey() {
+        return teTopologyKey;
+    }
+
+    /**
+     * Sets the TE topology key of the event.
+     *
+     * @param teTopologyKey the teTopologyKey to set
+     */
+    public void setTeTopologyKey(TeTopologyKey teTopologyKey) {
+        this.teTopologyKey = teTopologyKey;
+    }
+
+    /**
+     * Returns the TE node key of the event.
+     *
+     * @return the teNodeKey
+     */
+    public TeNodeKey teNodeKey() {
+        return teNodeKey;
+    }
+
+    /**
+     * Sets the TE node key of the event.
+     *
+     * @param teNodeKey the teNodeKey to set
+     */
+    public void setTeNodeKey(TeNodeKey teNodeKey) {
+        this.teNodeKey = teNodeKey;
+    }
+
+    /**
+     * Returns the TE link key of the event.
+     *
+     * @return the teLinkKey
+     */
+    public TeLinkTpGlobalKey teLinkKey() {
+        return teLinkKey;
+    }
+
+    /**
+     * Sets the TE link key of the event.
+     *
+     * @param teLinkKey the teLinkKey to set
+     */
+    public void setTeLinkKey(TeLinkTpGlobalKey teLinkKey) {
+        this.teLinkKey = teLinkKey;
+    }
+
+    /**
+     * Returns the network key of the event.
+     *
+     * @return the networkKey
+     */
+    public KeyId networkKey() {
+        return networkKey;
+    }
+
+    /**
+     * Sets the network key of the event.
+     *
+     * @param networkKey the networkKey to set
+     */
+    public void setNetworkKey(KeyId networkKey) {
+        this.networkKey = networkKey;
+    }
+
+    /**
+     * Returns the network node key of the event.
+     *
+     * @return the networkNodeKey
+     */
+    public NetworkNodeKey networkNodeKey() {
+        return networkNodeKey;
+    }
+
+    /**
+     * Sets the network node key of the event.
+     *
+     * @param networkNodeKey the networkNodeKey to set
+     */
+    public void setNetworkNodeKey(NetworkNodeKey networkNodeKey) {
+        this.networkNodeKey = networkNodeKey;
+    }
+
+    /**
+     * Returns the network link key of the event.
+     *
+     * @return the networkLinkKey
+     */
+    public NetworkLinkKey networkLinkKey() {
+        return networkLinkKey;
+    }
+
+    /**
+     * Sets the network link key of the event.
+     *
+     * @param networkLinkKey the networkLinkKey to set
+     */
+    public void setNetworkLinkKey(NetworkLinkKey networkLinkKey) {
+        this.networkLinkKey = networkLinkKey;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("type", type)
+                .add("teTopologyKey", teTopologyKey)
+                .add("teNodeKey", teNodeKey)
+                .add("teLinkKey", teLinkKey)
+                .add("networkKey", networkKey)
+                .add("networkNodeKey", networkNodeKey)
+                .add("networkLinkKey", networkLinkKey)
+                .toString();
+    }
+
+}
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
new file mode 100644
index 0000000..9ba407a
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStore.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+
+import org.onosproject.store.Store;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.TeTopologies;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+
+/**
+ * Inventory of TE network topology.
+ */
+public interface TeTopologyStore
+        extends Store<TeTopologyEvent, TeTopologyStoreDelegate> {
+
+    /**
+     * Returns a collection of currently known networks.
+     *
+     * @return a collection of stored networks
+     */
+    List<Network> networks();
+
+    /**
+     * Returns a network.
+     *
+     * @param  networkId network id in URI format
+     * @return value of network
+     */
+    Network network(KeyId networkId);
+
+    /**
+     * Updates a network.
+     *
+     * @param network value of the network to be updated
+     */
+    void updateNetwork(Network network);
+
+    /**
+     * Removes a network.
+     *
+     * @param  networkId network id in URI format
+     */
+    void removeNetwork(KeyId networkId);
+
+    /**
+     * Returns a network link.
+     *
+     * @param linkKey link key
+     * @return value of network link
+     */
+    NetworkLink networkLink(NetworkLinkKey linkKey);
+
+    /**
+     * Updates a network link.
+     *
+     * @param linkKey link key
+     * @param link link object to be updated
+    */
+    void updateNetworkLink(NetworkLinkKey linkKey, NetworkLink link);
+
+    /**
+     * Removes a network link.
+     *
+     * @param linkKey link key
+     */
+    void removeNetworkLink(NetworkLinkKey linkKey);
+
+    /**
+     * Returns a network node.
+     *
+     * @param nodeKey node key
+     * @return value of network node
+     */
+    NetworkNode networkNode(NetworkNodeKey nodeKey);
+
+    /**
+     * Updates a network node.
+     *
+     * @param nodeKey node key
+     * @param node node object to be updated
+     */
+    void updateNetworkNode(NetworkNodeKey nodeKey, NetworkNode node);
+
+    /**
+     * Removes a network node.
+     *
+     * @param nodeKey node key
+     */
+    void removeNetworkNode(NetworkNodeKey nodeKey);
+
+    /**
+     * Updates a terminationPoint.
+     *
+     * @param terminationPointKey termination point id
+     * @param terminationPoint termination point object to be updated
+     */
+    void updateTerminationPoint(TerminationPointKey terminationPointKey,
+                                TerminationPoint terminationPoint);
+
+    /**
+     * Removes a terminationPoint.
+     *
+     * @param terminationPointKey termination point id
+     */
+    void removeTerminationPoint(TerminationPointKey terminationPointKey);
+
+    /**
+     * Returns a collection of currently known TE topologies.
+     *
+     * @return a collection of topologies
+     */
+    TeTopologies teTopologies();
+
+    /**
+     * Returns the TE Topology identified by its Id.
+     *
+     * @param  topologyId TE topology Key
+     * @return value of TeTopology
+     */
+    TeTopology teTopology(TeTopologyKey topologyId);
+
+    /**
+     * Creates or updates a TE topology.
+     *
+     * @param teTopology value of the TE topology to be updated
+     */
+    void updateTeTopology(TeTopology teTopology);
+
+    /**
+     * Removes the TE Topology identified by its Id.
+     *
+     * @param topologyId TE topology key
+     */
+    void removeTeTopology(TeTopologyKey topologyId);
+
+    /**
+     * Returns the TE node identified by its Id.
+     *
+     * @param  nodeId the te node key
+     * @return value of node
+     */
+    TeNode teNode(TeNodeKey nodeId);
+
+    /**
+     * Creates or updates a TE Node.
+     *
+     * @param nodeKey te node id
+     * @param node node object to be updated
+     */
+    void updateTeNode(TeNodeKey nodeKey, TeNode node);
+
+    /**
+     * Removes the TE node identified by its Id.
+     *
+     * @param  nodeId the te node key
+     */
+    void removeTeNode(TeNodeKey nodeId);
+
+    /**
+     * Returns the TE link identified by its Id.
+     *
+     * @param  linkId the te link key
+     * @return value of link
+     */
+    TeLink teLink(TeLinkTpGlobalKey linkId);
+
+    /**
+     * Creates or updates a TE Link.
+     *
+     * @param linkKey link id
+     * @param link teLink object to be updated
+     */
+    void updateTeLink(TeLinkTpGlobalKey linkKey, TeLink link);
+
+    /**
+     * Removes the TE link identified by its Id.
+     *
+     * @param  linkId the te link key
+     */
+    void removeTeLink(TeLinkTpGlobalKey linkId);
+
+    /**
+     * Returns a tunnel termination point identified by its id.
+     *
+     * @param  ttpId the tunnel termination point key
+     * @return the tunnel termination point
+     */
+    TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId);
+
+    /**
+     * Returns the network Id for a TE Topology key.
+     *
+     * @param  teTopologyKey a TE topology key
+     * @return value of network Id
+     */
+    KeyId networkId(TeTopologyKey teTopologyKey);
+
+    /**
+     * Returns the network node key for a TE node key.
+     *
+     * @param  teNodeKey a TE node key
+     * @return value of network node key
+     */
+    NetworkNodeKey nodeKey(TeNodeKey teNodeKey);
+
+    /**
+     * Returns the network link key for a TE link key.
+     *
+     * @param  teLinkKey a TE node key
+     * @return value of network link key
+     */
+    NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey);
+
+    /**
+     * Returns the termination point key for a TE termination point key.
+     *
+     * @param  teTpKey a TE termination point key
+     * @return value of termination point key
+     */
+    TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey);
+
+    /**
+     * Returns the long value of next available TE topology id.
+     *
+     * @return value of TE topology id
+     */
+    long nextTeTopologyId();
+
+    /**
+     * Returns the next available TE node Id in a TE topology.
+     *
+     * @param topologyKey TE topology key
+     * @return value of TE node id
+     */
+    long nextTeNodeId(TeTopologyKey topologyKey);
+
+    /**
+     * Sets the next available TE node Id in a TE topology.
+     *
+     * @param topologyKey TE topology key
+     * @param nextNodeId value of next TE node id
+     */
+    void setNextTeNodeId(TeTopologyKey topologyKey, long nextNodeId);
+
+    /**
+     * Sets the queue to store the events originating from consistent maps.
+     *
+     * @param queue a blocking queue
+     */
+    void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue);
+
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStoreDelegate.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStoreDelegate.java
new file mode 100644
index 0000000..9b86164
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyStoreDelegate.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management.impl;
+
+import org.onosproject.store.StoreDelegate;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+
+/**
+ * Abstraction of TE networks store delegate.
+ */
+public interface TeTopologyStoreDelegate extends StoreDelegate<TeTopologyEvent> {
+
+}
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/package-info.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/package-info.java
new file mode 100644
index 0000000..89e3eee
--- /dev/null
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/package-info.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * TE Topology Management implementation.
+ */
+package org.onosproject.tetopology.management.impl;
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
new file mode 100644
index 0000000..564a938
--- /dev/null
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management;
+
+import java.util.BitSet;
+import java.util.List;
+import java.util.Map;
+
+import org.onlab.packet.Ip4Address;
+import org.onosproject.net.DeviceId;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.EncodingType;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.SwitchingType;
+import org.onosproject.tetopology.management.api.TeConstants;
+import org.onosproject.tetopology.management.api.TeStatus;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.link.CommonLinkData;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.DefaultTeLink;
+import org.onosproject.tetopology.management.api.link.ExternalLink;
+import org.onosproject.tetopology.management.api.link.LinkBandwidth;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.OduResource;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.link.TePathAttributes;
+import org.onosproject.tetopology.management.api.link.UnderlayPath;
+import org.onosproject.tetopology.management.api.node.CommonNodeData;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTeNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.DefaultTunnelTerminationPoint;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.NodeTpKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+import org.onosproject.tetopology.management.impl.TeMgrUtil;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Builds a sample abstract TE Topology, which consists of one node(represents
+ * an entire network), one inter-domain link and one TTP.
+ */
+public final class DefaultBuilder {
+    private static final String NODEIP = "100.10.10.10";
+    // Bandwidth in GigaBits/second
+    private static final float[] ODU0BW = {1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f};
+    private static final float[] ODU2BW = {10, 10, 10, 10, 10, 10, 10, 10};
+    private static final float[] ODU3BW = {40, 40, 40, 40, 40, 40, 40, 40};
+    private static final float[] ODU4BW = {100, 100, 100, 100, 100, 100, 100, 100};
+
+    private static final String ODU2 = "ODU2";
+    private static final String ODU3 = "ODU3";
+    private static final String ODU4 = "ODU4";
+
+    private static final long PROVIDER_ID = 0x100;
+    private static final long CLIENT_ID = 0x0a0a0a0a;
+    private static final long CLIENT_NIL = 0;
+    private static final long ABSTRACT_TOPOLOGY_ID = 100;
+    private static final long NATIVE_TOPOLOGY_ID = 1;
+    private static final long NUM_TPS = 1;
+    private static final long NUM_TTPS = 1;
+    private static final boolean ABSTRACT = true;
+    private static final boolean UNABSTRACT = false;
+    private static final int FIRST_INDEX = 0;
+    private static final long INTER_DOMAIN_LINK_PLUGID = 100;
+    private static final long LINK_COST = 500;
+    private static final long LINK_DELAY = 2000;
+    private static final long LINK_SRLG = 150;
+    private static final String DOMAIN_ID = "DomainX";
+
+    private static NetworkNode networkNode;
+    private static TeNode teNode;
+    private static NetworkLink networkLink;
+    private static TeLink teLink;
+    private static Network network;
+    private static TunnelTerminationPoint ttp;
+
+    private static TeTopologyKey teTopologyKey = new TeTopologyKey(PROVIDER_ID,
+                                                                   CLIENT_ID,
+                                                                   ABSTRACT_TOPOLOGY_ID);
+
+    // no instantiation
+    private DefaultBuilder() {
+    }
+
+    private static TunnelTerminationPoint ttpBuilder(long ttpId) {
+        return new DefaultTunnelTerminationPoint(ttpId, SwitchingType.OTN_TDM_CAPABLE,
+                                                 EncodingType.LSP_ENCODING_ODUK,
+                                                 new BitSet(TeConstants.FLAG_MAX_BITS),
+                                                 null, null,
+                                                 ODU2BW); //10G for ODU2
+    }
+
+    private static TerminationPoint tpBuilder(long teTpId) {
+        return new DefaultTerminationPoint(KeyId.keyId(Long.toString(teTpId)), null, teTpId);
+    }
+
+    private static NetworkNode nodeBuilder(String nodeIp, long numTps, long numTtps,
+                                          TeTopologyKey underlayTopologyId, TeNodeKey supportTeNodeId,
+                                          TeNodeKey sourceTeNodeId, boolean isAbstract) {
+        long teNodeId = Ip4Address.valueOf(nodeIp).toInt();
+        BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);
+
+        if (isAbstract) {
+            flags.set(TeNode.BIT_ABSTRACT);
+        }
+        CommonNodeData common = new CommonNodeData(nodeIp, TeStatus.UP, TeStatus.UP, flags);
+        Map<Long, ConnectivityMatrix> connMatrices = null;
+        List<Long> teTpIds = Lists.newArrayList();
+        Map<KeyId, TerminationPoint> tps = Maps.newHashMap();
+        for (long i = 0; i < numTps; i++) {
+            teTpIds.add(i);
+            tps.put(KeyId.keyId(Long.toString(i)), tpBuilder(i));
+        }
+        //TTP
+        Map<Long, TunnelTerminationPoint> ttps = Maps.newHashMap();
+        for (long i = 0; i < numTtps; i++) {
+            ttps.put(i, ttpBuilder(i));
+        }
+        ttp = ttps.get(FIRST_INDEX);
+        //TeNode
+        teNode = new DefaultTeNode(teNodeId, underlayTopologyId,
+                                   supportTeNodeId, sourceTeNodeId,
+                                          common, connMatrices, teTpIds, ttps, teTpIds);
+        List<NetworkNodeKey> supportingNodeIds = null;
+        if (supportTeNodeId != null) {
+            supportingNodeIds = Lists
+                    .newArrayList(TeMgrUtil.networkNodeKey(supportTeNodeId));
+        }
+
+        return new DefaultNetworkNode(KeyId.keyId(nodeIp), supportingNodeIds, teNode, tps);
+    }
+
+    private static LinkBandwidth linkBwBuilder(String odu) {
+
+        float[] maxBandwidth;  //Maximum bandwidth, Size is MAX_PRIORITY + 1
+        float[] avaiBandwidth; //Unreserved bandwidth, Size is MAX_PRIORITY + 1
+        float[] maxAvialLspBandwidth;  //Maximum available bandwidth for a LSP
+        float[] minAvialLspBandwidth;  //Minimum available bandwidth for a LSP
+        short odu0s;
+        short odu1s;
+        short odu2s;
+        short odu2es = 0;
+        short odu3s;
+        short odu4s;
+        short oduFlexes = 0;
+
+        switch (odu) {
+        case ODU3:
+            maxBandwidth = ODU3BW;
+            avaiBandwidth = ODU3BW;
+            maxAvialLspBandwidth = ODU3BW;
+            minAvialLspBandwidth = ODU0BW;
+            odu0s = 32;
+            odu1s = 16;
+            odu2s = 4;
+            odu3s = 1;
+            odu4s = 0;
+            break;
+        case ODU4:
+            maxBandwidth = ODU4BW;
+            avaiBandwidth = ODU4BW;
+            maxAvialLspBandwidth = ODU4BW;
+            minAvialLspBandwidth = ODU0BW;
+            odu0s = 80;
+            odu1s = 40;
+            odu2s = 10;
+            odu3s = 2;
+            odu4s = 1;
+            break;
+        default:
+            maxBandwidth = ODU2BW;
+            avaiBandwidth = ODU2BW;
+            maxAvialLspBandwidth = ODU2BW;
+            minAvialLspBandwidth = ODU0BW;
+            odu0s = 8;
+            odu1s = 4;
+            odu2s = 1;
+            odu3s = 0;
+            odu4s = 0;
+        }
+
+        OduResource oduRrc = new OduResource(odu0s, odu1s, odu2s, odu2es, odu3s,
+                                             odu4s, oduFlexes);
+        return new LinkBandwidth(maxBandwidth, avaiBandwidth, maxAvialLspBandwidth,
+                                 minAvialLspBandwidth, oduRrc);
+    }
+
+    private static NetworkLink linkBuilder(TeLinkTpKey teLinkKey, TeLinkTpKey peerTeLinkKey,
+                                          TeTopologyKey underlayTopologyId, TeLinkTpGlobalKey supportTeLinkId,
+                                          TeLinkTpGlobalKey sourceTeLinkId, boolean isAbstract, Long plugid,
+                                          Long cost, Long delay, List<Long> srlgs, String odu) {
+        //NetworkLink
+        KeyId linkId = TeMgrUtil.toNetworkLinkId(teLinkKey);
+        NodeTpKey source = new NodeTpKey(KeyId.keyId(Long.toString(teLinkKey.teNodeId())),
+                                         KeyId.keyId(Long.toString(teLinkKey.teLinkTpId())));
+        NodeTpKey destination = null;
+        if (peerTeLinkKey != null) {
+            destination = new NodeTpKey(KeyId.keyId(Long.toString(peerTeLinkKey.teNodeId())),
+                                        KeyId.keyId(Long.toString(peerTeLinkKey.teLinkTpId())));
+        }
+        List<NetworkLinkKey> supportingLinkIds = null;
+        if (supportTeLinkId != null) {
+            supportingLinkIds = Lists
+                    .newArrayList(TeMgrUtil.networkLinkKey(supportTeLinkId));
+        }
+        BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);
+        if (isAbstract) {
+            flags.set(TeLink.BIT_ABSTRACT);
+        }
+        ExternalLink externalLink = null;
+
+        if (plugid != null) {
+            // Inter-Domain Link
+            flags.set(TeLink.BIT_ACCESS_INTERDOMAIN);
+            externalLink = new ExternalLink(null, plugid);
+        }
+        UnderlayPath underlayPath = null;
+        Long adminGroup = null;
+        List<Long> interLayerLocks = null;
+        teLink = new DefaultTeLink(teLinkKey, peerTeLinkKey, underlayTopologyId,
+                                          supportTeLinkId, sourceTeLinkId,
+                                          new CommonLinkData(TeStatus.UP, TeStatus.UP, flags,
+                                                             SwitchingType.OTN_TDM_CAPABLE,
+                                                             EncodingType.LSP_ENCODING_ODUK,
+                                                             externalLink, underlayPath,
+                                                             new TePathAttributes(cost, delay, srlgs),
+                                                             adminGroup, interLayerLocks, linkBwBuilder(odu)));
+        return new DefaultNetworkLink(linkId, source, destination, supportingLinkIds, teLink);
+    }
+
+    private static Network networkBuilder(TeTopologyId teTopologyId, KeyId supportingNetworkId,
+                                         Map<KeyId, NetworkNode> nodes, Map<KeyId, NetworkLink> links,
+                                         boolean serverProvided, DeviceId ownerId) {
+        KeyId networkId = TeMgrUtil.toNetworkId(teTopologyId);
+        List<KeyId> supportingNetworkIds = null;
+        if (supportingNetworkId != null) {
+            supportingNetworkIds = Lists.newArrayList(supportingNetworkId);
+        }
+        return new DefaultNetwork(networkId, supportingNetworkIds, nodes, links, teTopologyId,
+                              serverProvided, ownerId);
+    }
+
+    /**
+     * Returns the key for the sample TE Topology.
+     *
+     * @return value of TE Topology key
+     */
+    public static TeTopologyKey teTopologyKey() {
+        return teTopologyKey;
+    }
+
+    /**
+     * Returns the abstract TE Node in the sample TE Topology.
+     *
+     * @return value of TE node
+     */
+    public static TeNode teNode() {
+        return teNode;
+    }
+
+    /**
+     * Returns the TE link in the sample TE Topology.
+     *
+     * @return value of TE link
+     */
+    public static TeLink teLink() {
+        return teLink;
+    }
+
+    /**
+     * Builds a sample abstract TE Topology, which consists of one abstract node
+     * representing an entire physical network, one inter-domain link and one
+     * TTP.
+     *
+     * @return value of network with an abstract TE Topology
+     */
+    public static Network buildSampleAbstractNetwork() {
+        TeTopologyKey underlayTopologyId = new TeTopologyKey(PROVIDER_ID,
+                                                             CLIENT_NIL,
+                                                             NATIVE_TOPOLOGY_ID);
+        Map<KeyId, NetworkNode> nodes = Maps.newHashMap();
+        networkNode = nodeBuilder(NODEIP, NUM_TPS, NUM_TTPS, underlayTopologyId,
+                                  null, null, ABSTRACT);
+        nodes.put(networkNode.nodeId(), networkNode);
+
+        Map<KeyId, NetworkLink> links = Maps.newHashMap();
+        TeLinkTpKey node1tp1 = new TeLinkTpKey(networkNode.teNode().teNodeId(),
+                                               networkNode.teNode()
+                                                       .teTerminationPointIds()
+                                                       .get(FIRST_INDEX));
+        networkLink = linkBuilder(node1tp1, null, null, null, null, UNABSTRACT,
+                                  INTER_DOMAIN_LINK_PLUGID, LINK_COST,
+                                  LINK_DELAY, Lists.newArrayList(LINK_SRLG),
+                                  ODU4);
+        links.put(networkLink.linkId(), networkLink);
+        DeviceId ownerId = DeviceId.deviceId(DOMAIN_ID);
+        TeTopologyId topologyId = new TeTopologyId(PROVIDER_ID, CLIENT_ID, Long
+                .toString(ABSTRACT_TOPOLOGY_ID));
+        network = networkBuilder(topologyId, null, nodes, links, false,
+                                 ownerId);
+        return network;
+    }
+
+}
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
new file mode 100644
index 0000000..3abaddc
--- /dev/null
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
@@ -0,0 +1,1033 @@
+/**
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management;
+
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
+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.slf4j.LoggerFactory.getLogger;
+
+import java.util.BitSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.tetopology.management.api.CommonTopologyData;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.DefaultTeTopologies;
+import org.onosproject.tetopology.management.api.DefaultTeTopology;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.OptimizationType;
+import org.onosproject.tetopology.management.api.TeConstants;
+import org.onosproject.tetopology.management.api.TeTopologies;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.TeUtils;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.DefaultTeLink;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrixKey;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTeNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.NodeTpKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+import org.onosproject.tetopology.management.impl.InternalNetwork;
+import org.onosproject.tetopology.management.impl.InternalNetworkLink;
+import org.onosproject.tetopology.management.impl.InternalNetworkNode;
+import org.onosproject.tetopology.management.impl.InternalTeLink;
+import org.onosproject.tetopology.management.impl.InternalTeNode;
+import org.onosproject.tetopology.management.impl.InternalTeTopology;
+import org.onosproject.tetopology.management.impl.InternalTerminationPoint;
+import org.onosproject.tetopology.management.impl.TeMgrUtil;
+import org.onosproject.tetopology.management.impl.TeTopologyManager;
+import org.onosproject.tetopology.management.impl.TeTopologyMapEvent;
+import org.onosproject.tetopology.management.impl.TeTopologyStore;
+import org.onosproject.tetopology.management.impl.TeTopologyStoreDelegate;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Implementation of the TE network store.
+ */
+@Component(immediate = true)
+@Service
+public class SimpleTeTopologyStore
+        extends AbstractStore<TeTopologyEvent, TeTopologyStoreDelegate>
+        implements TeTopologyStore {
+    private static final String STORE_NAME = "TE_NETWORK_TOPOLOGY_STORE";
+    private final Logger log = getLogger(getClass());
+
+    // Track TE topologies by TE Topology key
+    private Map<TeTopologyKey, InternalTeTopology> teTopologyMap = Maps
+            .newConcurrentMap();
+    // Track networks by network Id
+    private Map<KeyId, InternalNetwork> networkMap = Maps.newConcurrentMap();
+    // Track TE nodes by TE node key
+    private Map<TeNodeKey, InternalTeNode> teNodeMap = Maps.newConcurrentMap();
+    // Track ConnectivityMatrix by its key
+    private Map<ConnectivityMatrixKey, ConnectivityMatrix> connMatrixMap = Maps
+            .newConcurrentMap();
+    // Track Tunnel Termination Points by its key
+    private Map<TtpKey, TunnelTerminationPoint> ttpMap = Maps
+            .newConcurrentMap();
+    // Track network nodes by network node key
+    private Map<NetworkNodeKey, InternalNetworkNode> networkNodeMap = Maps
+            .newConcurrentMap();
+    // Track TE links by its key
+    private Map<TeLinkTpGlobalKey, InternalTeLink> teLinkMap = Maps
+            .newConcurrentMap();
+    // Track network links by network link key
+    private Map<NetworkLinkKey, InternalNetworkLink> networkLinkMap = Maps
+            .newConcurrentMap();
+    // Track Termination points by termination point key
+    private Map<TerminationPointKey, InternalTerminationPoint> tpMap = Maps
+            .newConcurrentMap();
+    // Track termination point keys by TE termination point Key
+    private Map<TeLinkTpGlobalKey, TerminationPointKey> tpKeyMap = Maps
+            .newConcurrentMap();
+
+    @Activate
+    public void activate() {
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        teTopologyMap.clear();
+        networkMap.clear();
+        teNodeMap.clear();
+        connMatrixMap.clear();
+        networkNodeMap.clear();
+        teLinkMap.clear();
+        networkLinkMap.clear();
+        tpMap.clear();
+        tpKeyMap.clear();
+        ttpMap.clear();
+        log.info("Stopped");
+    }
+
+    @Override
+    public TeTopologies teTopologies() {
+        Map<TeTopologyKey, TeTopology> teTopologies = Maps.newHashMap();
+        if (MapUtils.isNotEmpty(teTopologyMap)) {
+            for (TeTopologyKey key : teTopologyMap.keySet()) {
+                teTopologies.put(key, teTopology(key));
+            }
+        }
+        return new DefaultTeTopologies(STORE_NAME, teTopologies);
+    }
+
+    private TeTopology teTopology(TeTopologyKey topologyId,
+                                  InternalTeTopology intTopology) {
+        if (intTopology == null) {
+            return null;
+        }
+        Map<Long, TeNode> teNodes = null;
+        if (CollectionUtils.isNotEmpty(intTopology.teNodeKeys())) {
+            teNodes = Maps.newHashMap();
+            for (TeNodeKey key : intTopology.teNodeKeys()) {
+                teNodes.put(key.teNodeId(), teNode(key));
+            }
+        }
+        Map<TeLinkTpKey, TeLink> teLinks = null;
+        if (CollectionUtils.isNotEmpty(intTopology.teLinkKeys())) {
+            teLinks = Maps.newHashMap();
+            for (TeLinkTpGlobalKey key : intTopology.teLinkKeys()) {
+                teLinks.put(key.teLinkTpKey(), teLink(key));
+            }
+        }
+        return new DefaultTeTopology(topologyId, teNodes, teLinks,
+                                     intTopology.teTopologyId(),
+                                     intTopology.topologyData());
+    }
+
+    @Override
+    public TeTopology teTopology(TeTopologyKey topologyId) {
+        InternalTeTopology intTopology = teTopologyMap.get(topologyId);
+        return teTopology(topologyId, intTopology);
+    }
+
+    private void removeTopologyeMapEntrys(InternalTeTopology curTopology) {
+        // Remove TE nodes
+        if (CollectionUtils.isNotEmpty(curTopology.teNodeKeys())) {
+            for (TeNodeKey key : curTopology.teNodeKeys()) {
+                removeTeNode(key, true);
+            }
+        }
+        // Remove TE Links
+        if (CollectionUtils.isNotEmpty(curTopology.teLinkKeys())) {
+            for (TeLinkTpGlobalKey key : curTopology.teLinkKeys()) {
+                removeTeLink(key, true);
+            }
+        }
+    }
+
+    @Override
+    public void updateTeTopology(TeTopology teTopology) {
+        InternalTeTopology curTopology = teTopologyMap
+                .get(teTopology.teTopologyId());
+        if (curTopology != null) {
+            // Existing topology update
+            // Remove existing map entries first, which should be removed by
+            // its own events
+            removeTopologyeMapEntrys(curTopology);
+        }
+        // Update TE nodes
+        List<NetworkNodeKey> nodeIds = null;
+        if (MapUtils.isNotEmpty(teTopology.teNodes())) {
+            nodeIds = Lists.newArrayList();
+            for (Map.Entry<Long, TeNode> entry : teTopology.teNodes()
+                    .entrySet()) {
+                TeNodeKey teNodeKey = new TeNodeKey(teTopology.teTopologyId(),
+                                                    entry.getKey());
+                NetworkNodeKey nodeKey = TeMgrUtil.networkNodeKey(teNodeKey);
+                updateTeNode(teNodeKey, entry.getValue(), true, true, nodeKey);
+                nodeIds.add(nodeKey);
+            }
+        }
+        // Update TE links
+        List<NetworkLinkKey> linkIds = null;
+        if (MapUtils.isNotEmpty(teTopology.teLinks())) {
+            linkIds = Lists.newArrayList();
+            for (Map.Entry<TeLinkTpKey, TeLink> entry : teTopology.teLinks()
+                    .entrySet()) {
+                TeLinkTpGlobalKey teLinkKey = new TeLinkTpGlobalKey(teTopology
+                        .teTopologyId(), entry.getKey());
+                NetworkLinkKey linkKey = TeMgrUtil.networkLinkKey(teLinkKey);
+                updateTeLink(teLinkKey, entry.getValue(), true, true, linkKey);
+                linkIds.add(linkKey);
+            }
+        }
+        // Finally Update teTopologyMap
+        InternalTeTopology newTopology = new InternalTeTopology(teTopology);
+        teTopologyMap.put(teTopology.teTopologyId(), newTopology);
+
+        if (curTopology == null) {
+            // New topology, update networkMap
+            InternalNetwork intNetwork = new InternalNetwork();
+            intNetwork.setServerProvided(false);
+            intNetwork.setTeTopologyKey(teTopology.teTopologyId());
+            intNetwork.setNodeIds(nodeIds);
+            intNetwork.setLinkIds(linkIds);
+            networkMap.put(teTopology.networkId(), intNetwork);
+        }
+    }
+
+    @Override
+    public void removeTeTopology(TeTopologyKey topologyId) {
+        // Remove it from teTopologyMap
+        InternalTeTopology topology = teTopologyMap.remove(topologyId);
+        if (topology != null) {
+            removeTopologyeMapEntrys(topology);
+            // Remove it from networkMap;
+            networkMap.remove(topology.topologyData().networkId());
+        }
+    }
+
+    @Override
+    public List<Network> networks() {
+        if (MapUtils.isEmpty(networkMap)) {
+            return null;
+        }
+        List<Network> networks = Lists.newArrayList();
+        for (KeyId networkId : networkMap.keySet()) {
+            networks.add(network(networkId));
+        }
+        return networks;
+    }
+
+    private Network network(KeyId networkId, InternalNetwork curNetwork) {
+        if (curNetwork == null) {
+            return null;
+        }
+        List<KeyId> supportingNetworkIds = curNetwork.supportingNetworkIds();
+        Map<KeyId, NetworkNode> nodes = null;
+        if (CollectionUtils.isNotEmpty(curNetwork.nodeIds())) {
+            nodes = Maps.newHashMap();
+            for (NetworkNodeKey key : curNetwork.nodeIds()) {
+                nodes.put(key.nodeId(), networkNode(key));
+            }
+        }
+        Map<KeyId, NetworkLink> links = null;
+        if (CollectionUtils.isNotEmpty(curNetwork.linkIds())) {
+            links = Maps.newHashMap();
+            for (NetworkLinkKey key : curNetwork.linkIds()) {
+                links.put(key.linkId(), networkLink(key));
+            }
+        }
+        TeTopologyId topologyId = null;
+        DeviceId ownerId = null;
+        if (curNetwork.teTopologyKey() != null
+                && teTopology(curNetwork.teTopologyKey()) != null) {
+            topologyId = new TeTopologyId(curNetwork.teTopologyKey()
+                    .providerId(), curNetwork.teTopologyKey().clientId(),
+                                          teTopology(curNetwork.teTopologyKey())
+                                                  .teTopologyIdStringValue());
+            ownerId = teTopology(curNetwork.teTopologyKey()).ownerId();
+
+        }
+        return new DefaultNetwork(networkId, supportingNetworkIds, nodes, links,
+                                  topologyId, curNetwork.serverProvided(),
+                                  ownerId);
+    }
+
+    @Override
+    public Network network(KeyId networkId) {
+        InternalNetwork curNetwork = networkMap.get(networkId);
+        return network(networkId, curNetwork);
+    }
+
+    private void removeNetworkMapEntrys(InternalNetwork curNetwork,
+                                        boolean teRemove) {
+        // Remove TE nodes
+        if (CollectionUtils.isNotEmpty(curNetwork.nodeIds())) {
+            for (NetworkNodeKey key : curNetwork.nodeIds()) {
+                removeNetworkNode(key, teRemove);
+            }
+        }
+        // Remove TE Links
+        if (CollectionUtils.isNotEmpty(curNetwork.linkIds())) {
+            for (NetworkLinkKey key : curNetwork.linkIds()) {
+                removeNetworkLink(key, teRemove);
+            }
+        }
+    }
+
+    private TeTopologyKey newTeTopologyKey(TeTopologyId teTopologyId) {
+        long idValue;
+        try {
+            idValue = Long.parseLong(teTopologyId.topologyId());
+        } catch (NumberFormatException e) {
+            // Can't get the long value from the string.
+            // Use an assigned id value from local id pool,
+            // Ideally id should be assigned per provider base.
+            idValue = nextTeTopologyId();
+        }
+        return new TeTopologyKey(teTopologyId.providerId(),
+                                 teTopologyId.clientId(), idValue);
+    }
+
+    @Override
+    public void updateNetwork(Network network) {
+        InternalNetwork curNetwork = networkMap.get(network.networkId());
+        if (curNetwork != null) {
+            // Existing topology update
+            // Remove existing map entries first,
+            removeNetworkMapEntrys(curNetwork, false);
+        }
+        TeTopologyKey topoKey = null;
+        if (network.teTopologyId() != null) {
+            topoKey = newTeTopologyKey(network.teTopologyId());
+        }
+        // Update TE nodes
+        List<TeNodeKey> teNodeKeys = null;
+        if (MapUtils.isNotEmpty(network.nodes())) {
+            teNodeKeys = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkNode> entry : network.nodes()
+                    .entrySet()) {
+                NetworkNodeKey nodeKey = new NetworkNodeKey(network.networkId(),
+                                                            entry.getKey());
+                TeNodeKey teNodeKey = null;
+                if (topoKey != null && entry.getValue().teNode() != null) {
+                    teNodeKey = new TeNodeKey(topoKey, entry.getValue().teNode()
+                            .teNodeId());
+                }
+                updateNetworkNode(nodeKey, entry.getValue(), true, false,
+                                  teNodeKey);
+                teNodeKeys.add(teNodeKey);
+            }
+        }
+        // Update TE links
+        List<TeLinkTpGlobalKey> teLinkKeys = null;
+        if (MapUtils.isNotEmpty(network.links())) {
+            teLinkKeys = Lists.newArrayList();
+            for (Map.Entry<KeyId, NetworkLink> entry : network.links()
+                    .entrySet()) {
+                NetworkLinkKey linkKey = new NetworkLinkKey(network.networkId(),
+                                                            entry.getKey());
+                TeLinkTpGlobalKey teLinkKey = null;
+                if (topoKey != null && entry.getValue().teLink() != null) {
+                    teLinkKey = new TeLinkTpGlobalKey(topoKey, entry.getValue()
+                            .teLink().teLinkKey());
+                }
+                updateNetworkLink(linkKey, entry.getValue(), true, false,
+                                  teLinkKey);
+                teLinkKeys.add(teLinkKey);
+            }
+        }
+
+        // New network, update TE Topology first
+        if (curNetwork == null) {
+            InternalTeTopology intTopo = new InternalTeTopology(network
+                    .teTopologyId().topologyId());
+            intTopo.setTeNodeKeys(teNodeKeys);
+            intTopo.setTeLinkKeys(teLinkKeys);
+            BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);
+            flags.set(TeTopology.BIT_LEARNT);
+            if (network.teTopologyId()
+                    .clientId() == TeTopologyManager.DEFAULT_PROVIDER_ID) {
+                // Hard rule for now
+                flags.set(TeTopology.BIT_CUSTOMIZED);
+            }
+            CommonTopologyData common = new CommonTopologyData(network
+                    .networkId(), OptimizationType.NOT_OPTIMIZED, flags, network
+                            .ownerId());
+            intTopo.setTopologydata(common);
+            teTopologyMap.put(topoKey, intTopo);
+            // Assume new topology
+            TeTopologyEvent topologyEvent = new TeTopologyEvent(TE_TOPOLOGY_ADDED,
+                                                                teTopology(topoKey));
+            notifyDelegate(topologyEvent);
+        }
+        // Finally Update networkMap
+        InternalNetwork newNetwork = new InternalNetwork(network);
+        newNetwork.setTeTopologyKey(topoKey);
+        networkMap.put(network.networkId(), newNetwork);
+        // Assume new network
+        TeTopologyEvent topologyEvent = new TeTopologyEvent(NETWORK_ADDED,
+                                                            network(network
+                                                                    .networkId()));
+        notifyDelegate(topologyEvent);
+    }
+
+    @Override
+    public void removeNetwork(KeyId networkId) {
+        // Remove it from networkMap
+        InternalNetwork network = networkMap.remove(networkId);
+        TeTopologyEvent topologyEvent = new TeTopologyEvent(NETWORK_REMOVED,
+                                                            new DefaultNetwork(networkId,
+                                                                               null,
+                                                                               null,
+                                                                               null,
+                                                                               null,
+                                                                               false,
+                                                                               null));
+        notifyDelegate(topologyEvent);
+        if (network != null && network.teTopologyKey() != null) {
+            removeNetworkMapEntrys(network, false);
+            teTopologyMap.remove(network.teTopologyKey());
+            topologyEvent = new TeTopologyEvent(TE_TOPOLOGY_REMOVED,
+                                                new DefaultTeTopology(network
+                                                        .teTopologyKey(), null, null, null, null));
+            notifyDelegate(topologyEvent);
+        }
+    }
+
+    private TeNode teNode(TeNodeKey nodeKey, InternalTeNode intNode) {
+        if (intNode == null) {
+            return null;
+        }
+        Map<Long, ConnectivityMatrix> connMatrices = null;
+        if (CollectionUtils.isNotEmpty(intNode.connMatrixKeys())) {
+            connMatrices = Maps.newHashMap();
+            for (ConnectivityMatrixKey key : intNode.connMatrixKeys()) {
+                connMatrices.put(key.entryId(), connMatrixMap.get(key));
+            }
+        }
+        List<Long> teLinkIds = null;
+        if (CollectionUtils.isNotEmpty(intNode.teLinkTpKeys())) {
+            teLinkIds = Lists.newArrayList();
+            for (TeLinkTpGlobalKey key : intNode.teLinkTpKeys()) {
+                teLinkIds = TeUtils.addListElement(teLinkIds, key.teLinkTpId());
+            }
+        }
+        List<Long> tps = null;
+        if (CollectionUtils.isNotEmpty(intNode.teTpKeys())) {
+            tps = Lists.newArrayList();
+            for (TeLinkTpGlobalKey key : intNode.teTpKeys()) {
+                tps = TeUtils.addListElement(tps, key.teLinkTpId());
+            }
+        }
+        Map<Long, TunnelTerminationPoint> ttps = null;
+        if (CollectionUtils.isNotEmpty(intNode.ttpKeys())) {
+            ttps = Maps.newHashMap();
+            for (TtpKey key : intNode.ttpKeys()) {
+                ttps.put(key.ttpId(), ttpMap.get(key));
+            }
+        }
+        return new DefaultTeNode(nodeKey.teNodeId(),
+                                 intNode.underlayTopologyKey(),
+                                 intNode.supportNodeKey(),
+                                 intNode.sourceTeNodeKey(), intNode.teData(),
+                                 connMatrices, teLinkIds, ttps, tps);
+    }
+
+    @Override
+    public TeNode teNode(TeNodeKey nodeKey) {
+        InternalTeNode intNode = teNodeMap.get(nodeKey);
+        return teNode(nodeKey, intNode);
+    }
+
+    private void removeTeNodeMapEntrys(InternalTeNode intNode) {
+        // Remove connMatrixMap entries for the node
+        if (CollectionUtils.isNotEmpty(intNode.connMatrixKeys())) {
+            for (ConnectivityMatrixKey key : intNode.connMatrixKeys()) {
+                connMatrixMap.remove(key);
+            }
+        }
+        // Remove ttpMap entries for the node
+        if (CollectionUtils.isNotEmpty(intNode.ttpKeys())) {
+            for (TtpKey key : intNode.ttpKeys()) {
+                ttpMap.remove(key);
+            }
+        }
+    }
+
+    private void updateTeNode(TeNodeKey nodeKey, TeNode node,
+                              boolean parentUpdate, boolean teNodeUpdate,
+                              NetworkNodeKey networkNodeKey) {
+        InternalTeTopology intTopo = teTopologyMap.get(nodeKey.teTopologyKey());
+        if (intTopo == null && !parentUpdate) {
+            log.error("TE Topology is not in dataStore for nodeUpdate {}",
+                      nodeKey);
+            return;
+        }
+        InternalTeNode curNode = teNodeMap.get(nodeKey);
+        // Update connMatrixMap
+        if (MapUtils.isNotEmpty(node.connectivityMatrices())) {
+            for (Map.Entry<Long, ConnectivityMatrix> entry : node
+                    .connectivityMatrices().entrySet()) {
+                connMatrixMap
+                        .put(new ConnectivityMatrixKey(nodeKey, entry.getKey()),
+                             entry.getValue());
+            }
+        }
+        // Update ttpMap
+        if (MapUtils.isNotEmpty(node.tunnelTerminationPoints())) {
+            for (Map.Entry<Long, TunnelTerminationPoint> entry : node
+                    .tunnelTerminationPoints().entrySet()) {
+                ttpMap.put(new TtpKey(nodeKey, entry.getKey()),
+                           entry.getValue());
+            }
+        }
+        // Update TE Termination Points
+
+        // Update teNodeMap
+        InternalTeNode intNode = new InternalTeNode(nodeKey, node,
+                                                    networkNodeKey,
+                                                    parentUpdate);
+        teNodeMap.put(nodeKey, intNode);
+        if (curNode == null && !parentUpdate && intTopo != null) {
+            // Update InternalTeTopology
+            intTopo.setChildUpdate(true);
+            TeUtils.addListElement(intTopo.teNodeKeys(), nodeKey);
+        }
+        // Update networkNodeMap
+        if (teNodeUpdate) {
+            updateNetworkNode(networkNodeKey, networkNode(node), parentUpdate,
+                              teNodeUpdate, nodeKey);
+        }
+    }
+
+    private NetworkNode networkNode(TeNode node) {
+        KeyId nodeId = KeyId.keyId(Long.toString(node.teNodeId()));
+        List<NetworkNodeKey> supportingNodeIds = null;
+        if (node.supportingTeNodeId() != null) {
+            supportingNodeIds = Lists.newArrayList();
+            supportingNodeIds.add(new NetworkNodeKey(TeMgrUtil.toNetworkId((node
+                    .supportingTeNodeId().teTopologyKey())), KeyId.keyId(Long
+                            .toString(node.supportingTeNodeId().teNodeId()))));
+        }
+        Map<KeyId, TerminationPoint> tps = null;
+        if (node.teTerminationPointIds() != null) {
+            tps = Maps.newHashMap();
+            for (Long teTpId : node.teTerminationPointIds()) {
+                tps.put(KeyId.keyId(Long.toString(teTpId)),
+                        new DefaultTerminationPoint(KeyId
+                                .keyId(Long.toString(teTpId)), null, teTpId));
+            }
+        }
+        return new DefaultNetworkNode(nodeId, supportingNodeIds, node, tps);
+    }
+
+    @Override
+    public void updateTeNode(TeNodeKey nodeKey, TeNode node) {
+        updateTeNode(nodeKey, node, false, true,
+                     TeMgrUtil.networkNodeKey(nodeKey));
+    }
+
+    private void removeTeNode(TeNodeKey nodeKey, boolean teNodeRemove) {
+        // Remove it from InternalTeTopology first
+        InternalTeTopology intTopo = teTopologyMap.get(nodeKey.teTopologyKey());
+        if (intTopo != null
+                && CollectionUtils.isNotEmpty(intTopo.teNodeKeys())) {
+            intTopo.setChildUpdate(true);
+            intTopo.teNodeKeys().remove(nodeKey);
+        }
+        // Then remove it from teNodeMap
+        InternalTeNode node = teNodeMap.remove(nodeKey);
+        removeTeNodeMapEntrys(node);
+        // Remove it from networkNodeMap
+        if (teNodeRemove && node != null) {
+            removeNetworkNode(node.networkNodeKey(), teNodeRemove);
+        }
+    }
+
+    @Override
+    public void removeTeNode(TeNodeKey nodeKey) {
+        removeTeNode(nodeKey, true);
+    }
+
+    private NetworkNode networkNode(NetworkNodeKey nodeKey,
+                                    InternalNetworkNode intNode) {
+        if (intNode == null) {
+            return null;
+        }
+        Map<KeyId, TerminationPoint> tps = Maps.newHashMap();
+        for (KeyId tpId : intNode.tpIds()) {
+            tps.put(tpId,
+                    terminationPoint(new TerminationPointKey(nodeKey, tpId)));
+
+        }
+        return new DefaultNetworkNode(nodeKey.nodeId(),
+                                      intNode.supportingNodeIds(),
+                                      teNode(intNode.teNodeKey()), tps);
+    }
+
+    @Override
+    public NetworkNode networkNode(NetworkNodeKey nodeKey) {
+        InternalNetworkNode intNode = networkNodeMap.get(nodeKey);
+        return networkNode(nodeKey, intNode);
+    }
+
+    private void updateNetworkNode(NetworkNodeKey nodeKey, NetworkNode node,
+                                   boolean parentUpdate, boolean teNodeUpdate,
+                                   TeNodeKey teNodeKey) {
+        InternalNetwork intNework = null;
+        if (!parentUpdate) {
+            intNework = networkMap.get(nodeKey.networkId());
+            if (intNework == null) {
+                log.error("Network is not in dataStore for nodeUpdate {}",
+                          nodeKey);
+                return;
+            }
+        }
+
+        InternalNetworkNode exNode = networkNodeMap.get(nodeKey);
+        if (exNode != null && CollectionUtils.isNotEmpty(exNode.tpIds())) {
+            // Remove the TerminationPoints first
+            for (KeyId tpId : exNode.tpIds()) {
+                removeTerminationPoint(new TerminationPointKey(nodeKey, tpId));
+            }
+        }
+
+        if (MapUtils.isNotEmpty(node.terminationPoints())) {
+            // Update with new TerminationPoints
+            for (Map.Entry<KeyId, TerminationPoint> entry : node
+                    .terminationPoints().entrySet()) {
+                updateTerminationPoint(new TerminationPointKey(nodeKey,
+                                                               entry.getKey()),
+                                       entry.getValue(), parentUpdate,
+                                       teNodeKey);
+            }
+        }
+
+        // Update teNodeMap first
+        if (!teNodeUpdate && teNodeKey != null && node.teNode() != null) {
+            updateTeNode(teNodeKey, node.teNode(), parentUpdate, teNodeUpdate,
+                         nodeKey);
+        }
+        // Update networkNodeMap
+        InternalNetworkNode intNode = new InternalNetworkNode(node,
+                                                              parentUpdate);
+        intNode.setTeNodeKey(teNodeKey);
+        networkNodeMap.put(nodeKey, intNode);
+        if (exNode == null && !parentUpdate && intNework != null) {
+            // Update the InternalNetwork
+            intNework.setChildUpdate(true);
+            TeUtils.addListElement(intNework.nodeIds(), nodeKey);
+        }
+    }
+
+    @Override
+    public void updateNetworkNode(NetworkNodeKey nodeKey, NetworkNode node) {
+        TeNodeKey teNodeKey = null;
+        if (node.teNode() != null) {
+            teNodeKey = new TeNodeKey(networkMap.get(nodeKey.networkId())
+                    .teTopologyKey(), node.teNode().teNodeId());
+        }
+        updateNetworkNode(nodeKey, node, false, false, teNodeKey);
+    }
+
+    private void removeNetworkNode(NetworkNodeKey nodeKey,
+                                   boolean teNodeRemove) {
+        // Update the InternalNetwork
+        InternalNetwork intNework = networkMap.get(nodeKey.networkId());
+        if (intNework != null
+                && CollectionUtils.isNotEmpty(intNework.nodeIds())) {
+            intNework.setChildUpdate(true);
+            intNework.nodeIds().remove(nodeKey.nodeId());
+        }
+        InternalNetworkNode intNode = networkNodeMap.remove(nodeKey);
+        if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
+            // Remove the TerminationPoints first
+            for (KeyId tpId : intNode.tpIds()) {
+                removeTerminationPoint(new TerminationPointKey(nodeKey, tpId));
+            }
+        }
+        if (!teNodeRemove && intNode != null) {
+            // Now remove it from teNodeMap
+            removeTeNode(intNode.teNodeKey(), teNodeRemove);
+        }
+    }
+
+    @Override
+    public void removeNetworkNode(NetworkNodeKey nodeKey) {
+        removeNetworkNode(nodeKey, false);
+    }
+
+    private TeLink teLink(TeLinkTpGlobalKey linkKey, InternalTeLink intLink) {
+        if (intLink == null) {
+            return null;
+        }
+        return new DefaultTeLink(linkKey.teLinkTpKey(), intLink.peerTeLinkKey(),
+                                 intLink.underlayTopologyKey(),
+                                 intLink.supportingLinkKey(),
+                                 intLink.sourceTeLinkKey(), intLink.teData());
+    }
+
+    @Override
+    public TeLink teLink(TeLinkTpGlobalKey linkKey) {
+        InternalTeLink intLink = teLinkMap.get(linkKey);
+        return teLink(linkKey, intLink);
+    }
+
+    private void updateTeLink(TeLinkTpGlobalKey linkKey, TeLink link,
+                              boolean parentUpdate, boolean teLinkUpdate,
+                              NetworkLinkKey networkLinkKey) {
+        InternalTeTopology intTopo = teTopologyMap.get(linkKey.teTopologyKey());
+        if (intTopo == null && !parentUpdate) {
+            log.error("TE Topology is not in dataStore for linkUpdate {}",
+                      linkKey);
+            return;
+        }
+        InternalTeNode intNode = teNodeMap.get(linkKey.teNodeKey());
+        if (intNode == null && !parentUpdate) {
+            log.error("TE node is not in dataStore for linkUpdate {}", linkKey);
+            return;
+        }
+        InternalTeLink exLink = teLinkMap.get(linkKey);
+
+        // Update teLinkMap
+        InternalTeLink intLink = new InternalTeLink(link, parentUpdate);
+        intLink.setNetworkLinkKey(networkLinkKey);
+        teLinkMap.put(linkKey, intLink);
+        if (exLink == null && !parentUpdate) {
+            if (intTopo != null) {
+                // Update the InternalTeTopology
+                intTopo.setChildUpdate(true);
+                intTopo.setTeLinkKeys(TeUtils
+                        .addListElement(intTopo.teLinkKeys(), linkKey));
+            }
+            if (intNode != null) {
+                // Update the InternalNode
+                intNode.setChildUpdate(true);
+                intNode.setTeLinkTpKeys(TeUtils
+                        .addListElement(intNode.teLinkTpKeys(), linkKey));
+            }
+        }
+
+        // Update networkLinkMap
+        if (teLinkUpdate) {
+            updateNetworkLink(networkLinkKey, networkLink(link), parentUpdate,
+                              teLinkUpdate, linkKey);
+        }
+    }
+
+    private NetworkLink networkLink(TeLink link) {
+        KeyId linkId = TeMgrUtil.toNetworkLinkId(link.teLinkKey());
+        NodeTpKey source = null;
+        if (link.teLinkKey() != null) {
+            source = new NodeTpKey(KeyId
+                    .keyId(Long.toString(link.teLinkKey().teNodeId())), KeyId
+                            .keyId(Long
+                                    .toString(link.teLinkKey().teLinkTpId())));
+        }
+        NodeTpKey dest = null;
+        if (link.peerTeLinkKey() != null) {
+            dest = new NodeTpKey(KeyId
+                    .keyId(Long.toString(link.peerTeLinkKey().teNodeId())),
+                                 KeyId.keyId(Long.toString(link.peerTeLinkKey()
+                                         .teLinkTpId())));
+        }
+        List<NetworkLinkKey> supportingLinkIds = null;
+        if (link.supportingTeLinkId() != null) {
+            supportingLinkIds = Lists.newArrayList();
+            supportingLinkIds.add(new NetworkLinkKey(TeMgrUtil.toNetworkId(link
+                    .supportingTeLinkId().teTopologyKey()), TeMgrUtil
+                            .toNetworkLinkId(link.supportingTeLinkId()
+                                    .teLinkTpKey())));
+        }
+        return new DefaultNetworkLink(linkId, source, dest, supportingLinkIds,
+                                      link);
+    }
+
+    @Override
+    public void updateTeLink(TeLinkTpGlobalKey linkKey, TeLink link) {
+        updateTeLink(linkKey, link, false, true,
+                     TeMgrUtil.networkLinkKey(linkKey));
+    }
+
+    private void removeTeLink(TeLinkTpGlobalKey linkKey, boolean teLinkRemove) {
+        // Remove it from InternalTeTopology first
+        InternalTeTopology intTopo = teTopologyMap.get(linkKey.teTopologyKey());
+        if (intTopo != null
+                && CollectionUtils.isNotEmpty(intTopo.teLinkKeys())) {
+            intTopo.setChildUpdate(true);
+            intTopo.teLinkKeys().remove(linkKey);
+        }
+        // Remove it from InternalTeNode
+        InternalTeNode intNode = teNodeMap.get(linkKey.teNodeKey());
+        if (intNode != null
+                && CollectionUtils.isNotEmpty(intNode.teLinkTpKeys())) {
+            intNode.setChildUpdate(true);
+            intNode.teLinkTpKeys().remove(linkKey);
+        }
+        // Then remove it from teLinkMap
+        InternalTeLink link = teLinkMap.remove(linkKey);
+        if (teLinkRemove && link != null) {
+            // Remove it from networkLinkMap
+            removeNetworkLink(link.networkLinkKey(), teLinkRemove);
+        }
+    }
+
+    @Override
+    public void removeTeLink(TeLinkTpGlobalKey linkKey) {
+        removeTeLink(linkKey, true);
+    }
+
+    private NetworkLink networkLink(NetworkLinkKey linkKey,
+                                    InternalNetworkLink intLink) {
+        if (intLink == null) {
+            return null;
+        }
+        return new DefaultNetworkLink(linkKey.linkId(), intLink.source(),
+                                      intLink.destination(),
+                                      intLink.supportingLinkIds(),
+                                      teLink(intLink.teLinkKey()));
+    }
+
+    @Override
+    public NetworkLink networkLink(NetworkLinkKey linkKey) {
+        InternalNetworkLink intLink = networkLinkMap.get(linkKey);
+        return networkLink(linkKey, intLink);
+    }
+
+    private void updateNetworkLink(NetworkLinkKey linkKey, NetworkLink link,
+                                   boolean parentUpdate, boolean teLinkUpdate,
+                                   TeLinkTpGlobalKey teLinkKey) {
+        InternalNetwork intNework = null;
+        if (!parentUpdate) {
+            intNework = networkMap.get(linkKey.networkId());
+            if (intNework == null) {
+                log.error("Network is not in dataStore for linkUpdate {}",
+                          linkKey);
+                return;
+            }
+        }
+
+        InternalNetworkLink exLink = networkLinkMap.get(linkKey);
+
+        // Now update teLinkMap first
+        if (!teLinkUpdate && teLinkKey != null) {
+            updateTeLink(teLinkKey, link.teLink(), parentUpdate, teLinkUpdate,
+                         linkKey);
+        }
+        // Update networkLinkMap
+        InternalNetworkLink intLink = new InternalNetworkLink(link,
+                                                              parentUpdate);
+        intLink.setTeLinkKey(teLinkKey);
+        networkLinkMap.put(linkKey, intLink);
+        if (exLink == null && !parentUpdate && intNework != null) {
+            // Update the InternalNetwork
+            intNework.setChildUpdate(true);
+            TeUtils.addListElement(intNework.linkIds(), linkKey);
+        }
+    }
+
+    @Override
+    public void updateNetworkLink(NetworkLinkKey linkKey, NetworkLink link) {
+        TeLinkTpGlobalKey teLinkKey = null;
+        if (link.teLink() != null) {
+            teLinkKey = new TeLinkTpGlobalKey(networkMap
+                    .get(linkKey.networkId()).teTopologyKey(),
+                                              link.teLink().teLinkKey());
+        }
+
+        updateNetworkLink(linkKey, link, false, false, teLinkKey);
+    }
+
+    private void removeNetworkLink(NetworkLinkKey linkKey,
+                                   boolean teLinkRemove) {
+        // Update the InternalNetwork
+        InternalNetwork intNework = networkMap.get(linkKey.networkId());
+        if (intNework != null
+                && CollectionUtils.isNotEmpty(intNework.linkIds())) {
+            intNework.setChildUpdate(true);
+            intNework.linkIds().remove(linkKey.linkId());
+        }
+        // Remove it from networkLinkMap
+        InternalNetworkLink intLink = networkLinkMap.remove(linkKey);
+        if (!teLinkRemove && intLink != null && intLink.teLinkKey() != null) {
+            // Now remove it from teLinkMap
+            removeTeLink(intLink.teLinkKey(), teLinkRemove);
+        }
+    }
+
+    @Override
+    public void removeNetworkLink(NetworkLinkKey linkKey) {
+        removeNetworkLink(linkKey, false);
+    }
+
+    private TerminationPoint terminationPoint(TerminationPointKey tpKey) {
+        InternalTerminationPoint intTp = tpMap.get(tpKey);
+        if (intTp == null) {
+            return null;
+        }
+        return new DefaultTerminationPoint(tpKey.tpId(),
+                                           intTp.supportingTpIds(),
+                                           intTp.teTpKey().teLinkTpId());
+    }
+
+    private void updateTerminationPoint(TerminationPointKey tpKey,
+                                        TerminationPoint tp,
+                                        boolean parentUpdate,
+                                        TeNodeKey teNodeKey) {
+        TeNodeKey myTeNodeKey;
+        InternalNetworkNode intNode = null;
+        if (!parentUpdate) {
+            intNode = networkNodeMap.get(tpKey.nodeId());
+            if (intNode == null) {
+                log.error(" node is not in dataStore for tp update {}", tpKey);
+                return;
+            }
+            myTeNodeKey = intNode.teNodeKey();
+        } else {
+            myTeNodeKey = teNodeKey;
+        }
+        TeLinkTpGlobalKey teTpKey = new TeLinkTpGlobalKey(myTeNodeKey,
+                                                          tp.teTpId());
+
+        boolean newTp = tpMap.get(tpKey) == null;
+        InternalTerminationPoint intTp = new InternalTerminationPoint(tp);
+        intTp.setTeTpKey(teTpKey);
+        tpMap.put(tpKey, intTp);
+        if (newTp) {
+            // Update tpKeyMap
+            tpKeyMap.put(teTpKey, tpKey);
+            if (!parentUpdate && intNode != null) {
+                // Update InternalNetworkNode
+                intNode.setChildUpdate(true);
+                intNode.setTpIds(TeUtils.addListElement(intNode.tpIds(),
+                                                        tpKey.tpId()));
+            }
+        }
+    }
+
+    @Override
+    public void updateTerminationPoint(TerminationPointKey tpKey,
+                                       TerminationPoint tp) {
+        updateTerminationPoint(tpKey, tp, false, null);
+    }
+
+    @Override
+    public void removeTerminationPoint(TerminationPointKey tpKey) {
+        // Update InternalNetworkNode
+        InternalNetworkNode intNode = networkNodeMap.get(tpKey.nodeId());
+        if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
+            intNode.setChildUpdate(true);
+            intNode.tpIds().remove(tpKey.tpId());
+        }
+        // Remove it from tpMap
+        InternalTerminationPoint tp = tpMap.remove(tpKey);
+        // Remove it from tpKeyMap
+        if (tp != null) {
+            tpKeyMap.remove(tp.teTpKey());
+        }
+    }
+
+    @Override
+    public TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId) {
+        return ttpMap.get(ttpId);
+    }
+
+    @Override
+    public long nextTeTopologyId() {
+        return 0;
+    }
+
+    @Override
+    public long nextTeNodeId(TeTopologyKey topoKey) {
+        return teTopologyMap.get(topoKey).nextTeNodeId();
+    }
+
+    @Override
+    public void setNextTeNodeId(TeTopologyKey topoKey, long nextNodeId) {
+        teTopologyMap.get(topoKey).setNextTeNodeId(nextNodeId);
+    }
+
+    @Override
+    public KeyId networkId(TeTopologyKey teTopologyKey) {
+        return teTopologyMap.get(teTopologyKey).topologyData().networkId();
+    }
+
+    @Override
+    public NetworkNodeKey nodeKey(TeNodeKey teNodeKey) {
+        return teNodeMap.get(teNodeKey).networkNodeKey();
+    }
+
+    @Override
+    public NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey) {
+        return teLinkMap.get(teLinkKey).networkLinkKey();
+    }
+
+    @Override
+    public TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey) {
+        return tpKeyMap.get(teTpKey);
+    }
+
+    @Override
+    public void setMapEventQueue(BlockingQueue<TeTopologyMapEvent> queue) {
+    }
+}
+
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
new file mode 100644
index 0000000..03d21fb
--- /dev/null
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/TeTopologyManagerTest.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.tetopology.management;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.net.NetTestTools.injectEventDispatcher;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
+import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
+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 java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.common.event.impl.TestEventDispatcher;
+import org.onosproject.event.Event;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyListener;
+import org.onosproject.tetopology.management.api.TeTopologyProvider;
+import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
+import org.onosproject.tetopology.management.api.TeTopologyProviderService;
+import org.onosproject.tetopology.management.api.TeTopologyService;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.impl.TeMgrUtil;
+import org.onosproject.tetopology.management.impl.TeTopologyManager;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Test TeTopology service and TeTopologyProvider service.
+ */
+public class TeTopologyManagerTest {
+    private static final ProviderId PID = new ProviderId("test", "TeTopologyManagerTest");
+
+    private TeTopologyManager mgr;
+    protected TeTopologyService service;
+    protected TeTopologyProviderRegistry registry;
+    protected TeTopologyProviderService providerService;
+    protected TestProvider provider;
+    protected TestListener listener = new TestListener();
+
+    @Before
+    public void setUp() {
+        mgr = new TeTopologyManager();
+        service = mgr;
+        registry = mgr;
+        mgr.store = new SimpleTeTopologyStore();
+
+        injectEventDispatcher(mgr, new TestEventDispatcher());
+
+        mgr.activateBasics();
+        service.addListener(listener);
+
+        provider = new TestProvider();
+        providerService = registry.register(provider);
+        assertTrue("providerService should not be null", providerService != null);
+        assertTrue("Provider should be registered",
+                   registry.getProviders().contains(provider.id()));
+    }
+
+    @After
+    public void tearDown() {
+        registry.unregister(provider);
+        assertFalse("provider should not be registered",
+                    registry.getProviders().contains(provider.id()));
+        service.removeListener(listener);
+        mgr.deactivateBasics();
+    }
+
+    private void createNetwork() {
+        Network originNetwork = DefaultBuilder.buildSampleAbstractNetwork();
+        providerService.networkUpdated(originNetwork);
+        Network network = service
+                .network(TeMgrUtil.toNetworkId(DefaultBuilder.teTopologyKey()));
+        assertNotNull("Network should be found", network);
+    }
+
+    /**
+     * Checks the right events are received when a network with TE topology is
+     * added.
+     */
+    @Test
+    public void networkAdded() {
+        createNetwork();
+        validateEvents(TE_TOPOLOGY_ADDED, NETWORK_ADDED);
+    }
+
+    /**
+     * Checks the TE topology components are set properly in Manager and Store
+     * when a network is added.
+     */
+    @Test
+    public void teTopologyVerify() {
+        createNetwork();
+        TeTopology teTopology = service
+                .teTopology(DefaultBuilder.teTopologyKey());
+        assertNotNull("TeTopology should be found", teTopology);
+        assertTrue("Number of TE nodes should be 1",
+                   teTopology.teNodes().size() == 1);
+        assertTrue("Number of TE links should be 1",
+                   teTopology.teLinks().size() == 1);
+        TeNode teNode = service
+                .teNode(new TeNodeKey(DefaultBuilder.teTopologyKey(),
+                                      DefaultBuilder.teNode().teNodeId()));
+        assertNotNull("TeNode should be found", teNode);
+        assertTrue("Number of TTPs should be 1",
+                   teNode.tunnelTerminationPoints().size() == 1);
+        TeLink teLink = service
+                .teLink(new TeLinkTpGlobalKey(DefaultBuilder
+                        .teTopologyKey(), DefaultBuilder.teLink().teLinkKey()));
+        assertNotNull("TeLink should be found", teLink);
+    }
+
+    /**
+     * Checks the right events are received when a network with TE topology is
+     * added and then removed.
+     */
+    @Test
+    public void networkRemoved() {
+        createNetwork();
+        providerService.networkRemoved(TeMgrUtil
+                .toNetworkId(DefaultBuilder.teTopologyKey()));
+        validateEvents(TE_TOPOLOGY_ADDED, NETWORK_ADDED, NETWORK_REMOVED,
+                       TE_TOPOLOGY_REMOVED);
+    }
+
+    /**
+     * Validates whether the manager receives the right events.
+     *
+     * @param types a set of types of control message event
+     */
+    protected void validateEvents(Enum... types) {
+        int i = 0;
+        assertEquals("wrong events received", types.length, listener.events.size());
+        for (Event event : listener.events) {
+            assertEquals("incorrect event type", types[i], event.type());
+            i++;
+        }
+        listener.events.clear();
+    }
+
+    private class TestProvider extends AbstractProvider implements TeTopologyProvider {
+        protected TestProvider() {
+            super(PID);
+        }
+    }
+
+    private static class TestListener implements TeTopologyListener {
+        final List<TeTopologyEvent> events = Lists.newArrayList();
+
+        @Override
+        public void event(TeTopologyEvent event) {
+            events.add(event);
+        }
+    }
+
+}
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/package-info.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/package-info.java
new file mode 100644
index 0000000..071f1d2
--- /dev/null
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The TE topology implementation test functions.
+ */
+package org.onosproject.tetopology.management;
diff --git a/apps/tetopology/pom.xml b/apps/tetopology/pom.xml
index fcf01a7..1e01d84 100644
--- a/apps/tetopology/pom.xml
+++ b/apps/tetopology/pom.xml
@@ -31,9 +31,7 @@
 
     <modules>
         <module>api</module>
-        <!--
         <module>app</module>
-        -->
     </modules>
 
 <!--