Merge "Leaving deprecated API in Neutron-Mapper"
authorMartin Sunal <msunal@cisco.com>
Tue, 26 Apr 2016 14:52:07 +0000 (14:52 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 26 Apr 2016 14:52:07 +0000 (14:52 +0000)
37 files changed:
sxp-mapper/pom.xml
sxp-mapper/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_mapper/SxpMapperProviderModule.java
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/SxpMapperProviderImpl.java [deleted file]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/DSAsyncDao.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/EPTemplateListener.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/IpPrefixEqualCommand.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/MasterDatabaseBindingListener.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableByKey.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleCachedDao.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleDao.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SxpMapperReactor.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperProviderImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtil.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandDirectImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandSubnetImpl.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/L3EPServiceUtil.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SubnetInfoKeyDecorator.java [new file with mode: 0644]
sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SxpListenerUtil.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImplTest.java [new file with mode: 0644]
sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtilTest.java [new file with mode: 0644]

index 99ad1f366098520b30207297106bfdb0b13b8557..09eb8806ed9780fbbf54cdf92d1b86d75b5ddf5f 100755 (executable)
                 <artifactId>sxp-api</artifactId>
                 <version>${sxp.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.sxp</groupId>
+                <artifactId>sxp-core</artifactId>
+                <version>${sxp.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
             <groupId>org.opendaylight.sxp</groupId>
             <artifactId>sxp-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.sxp</groupId>
+            <artifactId>sxp-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-net</groupId>
+            <artifactId>commons-net</artifactId>
+        </dependency>
 
         <!-- testing dependencies -->
         <dependency>
index 8f65147dbbfbcb4a0b0bfbb1f4f8d7868af41630..8a78441ec48b4ae9480c6db3ac622bafb052994b 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_mapper;
 
 
-import org.opendaylight.groupbasedpolicy.sxp.mapper.SxpMapperProviderImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.SxpMapperProviderImpl;
 
 /**
 * sxp-mapper impl module
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/SxpMapperProviderImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/SxpMapperProviderImpl.java
deleted file mode 100644 (file)
index d21c3d2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.groupbasedpolicy.sxp.mapper;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-
-/**
- * SxpMapper provider implementation.
- */
-public class SxpMapperProviderImpl implements AutoCloseable {
-
-    private final DataBroker dataBrokerDependency;
-    private final RpcProviderRegistry rpcRegistryDependency;
-
-    public SxpMapperProviderImpl(final DataBroker dataBrokerDependency, final RpcProviderRegistry rpcRegistryDependency) {
-        this.dataBrokerDependency = dataBrokerDependency;
-        this.rpcRegistryDependency = rpcRegistryDependency;
-    }
-
-    @Override
-    public void close() throws Exception {
-        //TODO: stub
-    }
-}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/DSAsyncDao.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/DSAsyncDao.java
new file mode 100644 (file)
index 0000000..ac31581
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Purpose: encapsulate access to DS by exposing
+ * <dl>
+ * <dt>read</dt>
+ * <dd>search through values (either in local cache or directly in DataStore)</dd>
+ * </dl>
+ *
+ * @param <K> data key type
+ * @param <V> data type
+ */
+public interface DSAsyncDao<K, V extends DataObject> {
+
+    /**
+     * @param key for search
+     * @return value found by key
+     */
+    ListenableFuture<Optional<V>> read(@Nonnull K key);
+
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/EPTemplateListener.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/EPTemplateListener.java
new file mode 100644 (file)
index 0000000..f7898e7
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Purpose: provide listener capability to EndPoint templates
+ */
+public interface EPTemplateListener<T extends DataObject> extends DataTreeChangeListener<T>, AutoCloseable {
+
+    InstanceIdentifier<SxpMapper> SXP_MAPPER_TEMPLATE_PARENT_PATH = InstanceIdentifier.create(SxpMapper.class);
+
+    //NOBODY
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/IpPrefixEqualCommand.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/IpPrefixEqualCommand.java
new file mode 100644 (file)
index 0000000..1c3a2cf
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+
+/**
+ * Purpose: provide different strategies for {@link IpPrefix} comparison
+ */
+public interface IpPrefixEqualCommand {
+
+    boolean isEqualTo(IpPrefix value);
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/MasterDatabaseBindingListener.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/MasterDatabaseBindingListener.java
new file mode 100644 (file)
index 0000000..6c9e2f8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.sxp.core.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Purpose: provide listener capability to {@link MasterDatabaseBinding} (Sxp - MasterDB)
+ */
+public interface MasterDatabaseBindingListener extends DataTreeChangeListener<MasterDatabaseBinding>, AutoCloseable {
+    /** path to SXP topology */
+    KeyedInstanceIdentifier<Topology, TopologyKey> SXP_TOPOLOGY_PATH = InstanceIdentifier.create(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(Configuration.TOPOLOGY_NAME)));
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableByKey.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/ReadableByKey.java
new file mode 100644 (file)
index 0000000..fc46e6d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+
+/**
+ * Purpose: simple asynchronous search interface allowing for custom key and returning list of values
+ *
+ * @param <X> special key type
+ * @param <V> value type
+ */
+public interface ReadableByKey<X, V> {
+
+    /**
+     * @param specialKey custom key to search by
+     * @return list of found values
+     */
+    ListenableFuture<Collection<V>> readBy(@Nonnull X specialKey);
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleCachedDao.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleCachedDao.java
new file mode 100644 (file)
index 0000000..d3e1390
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Purpose: encapsulate access to DS by exposing
+ * <dl>
+ * <dt>find</dt>
+ * <dd>search through cached values</dd>
+ * <dt>update</dt>
+ * <dd>stores given pair (key, value) to local cache</dd>
+ * </dl>
+ *
+ * @param <K> data key type
+ * @param <V> data type
+ */
+public interface SimpleCachedDao<K, V> extends SimpleDao<K, V> {
+
+    /**
+     * store given pair to local cache
+     *
+     * @param key   associated to value
+     * @param value associated to key
+     */
+    V update(@Nonnull K key, @Nullable V value);
+
+    /**
+     * invalidate all cache entries
+     */
+    void invalidateCache();
+
+    /**
+     * @return true if there is nothing cached
+     */
+    boolean isEmpty();
+
+    /**
+     * @return unmodifiable iterator through all cached values
+     */
+    Iterable<V> values();
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleDao.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SimpleDao.java
new file mode 100644 (file)
index 0000000..1616eac
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nonnull;
+
+/**
+ * Purpose: encapsulate access to DS by exposing
+ * <dl>
+ * <dt>find</dt>
+ * <dd>search through available values (e.g.: in  local cache)</dd>
+ * </dl>
+ *
+ * @param <K> data key type
+ * @param <V> data type
+ */
+public interface SimpleDao<K, V> {
+
+    /**
+     * @param key for search
+     * @return value found by key
+     */
+    Optional<V> find(@Nonnull K key);
+
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SxpMapperReactor.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/api/SxpMapperReactor.java
new file mode 100644 (file)
index 0000000..304c95d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sxp.mapper.api;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Purpose: process given ip-sgt binding and EP-template in order to create L3-EP
+ */
+public interface SxpMapperReactor {
+
+    /**
+     * apply sgt/ip binding on policy template and delegate to appropriate GBP service
+     *  @param epPolicyTemplate template
+     * @param masterDatabaseBinding sxpMasterDB item
+     */
+    ListenableFuture<RpcResult<Void>> processPolicyAndSxpMasterDB(EndpointPolicyTemplateBySgt epPolicyTemplate, MasterDatabaseBinding masterDatabaseBinding);
+
+    /**
+     * apply sgt/ip binding on forwarding template and delegate to appropriate GBP service
+     *  @param epForwardingTemplate template
+     * @param masterDatabaseBinding sxpMasterDB item
+     */
+    ListenableFuture<RpcResult<Void>> processForwardingAndSxpMasterDB(EndpointForwardingTemplateBySubnet epForwardingTemplate, MasterDatabaseBinding masterDatabaseBinding);
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperProviderImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperProviderImpl.java
new file mode 100644 (file)
index 0000000..1e6fd91
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.SimpleCachedDaoEPForwardingTemplateImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.SimpleCachedDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EPForwardingTemplateDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.EPPolicyTemplateDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao.MasterDatabaseBindingDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.EPForwardingTemplateListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.EPPolicyTemplateListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen.MasterDatabaseBindingListenerImpl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SxpMapper provider implementation.
+ */
+public class SxpMapperProviderImpl implements AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SxpMapperProviderImpl.class);
+
+    private final DataBroker dataBrokerDependency;
+    private final RpcProviderRegistry rpcRegistryDependency;
+    private final MasterDatabaseBindingListenerImpl sxpDatabaseListener;
+    private final SxpMapperReactor sxpMapperReactor;
+    private final EPTemplateListener epPolicyTemplateListener;
+    private final EPTemplateListener epForwardingTemplateListener;
+
+    public SxpMapperProviderImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistryDependency) {
+        LOG.info("starting SxmMapper ..");
+        this.dataBrokerDependency = dataBroker;
+        this.rpcRegistryDependency = rpcRegistryDependency;
+
+        final EndpointService endpointService = rpcRegistryDependency.getRpcService(EndpointService.class);
+        sxpMapperReactor = new SxpMapperReactorImpl(endpointService);
+
+        final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao = new SimpleCachedDaoImpl<>();
+        final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateCachedDao =
+                new SimpleCachedDaoEPForwardingTemplateImpl();
+        final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> masterDBBindingCachedDao = new SimpleCachedDaoImpl<>();
+
+        final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao = new EPPolicyTemplateDaoImpl(dataBroker, epPolicyTemplateCachedDao);
+        final EPForwardingTemplateDaoImpl epForwardingTemplateDao = new EPForwardingTemplateDaoImpl(dataBroker,
+                epForwardingTemplateCachedDao);
+        final  MasterDatabaseBindingDaoImpl masterDBBindingDao = new MasterDatabaseBindingDaoImpl(dataBroker, masterDBBindingCachedDao);
+
+        sxpDatabaseListener = new MasterDatabaseBindingListenerImpl(dataBroker, sxpMapperReactor, masterDBBindingCachedDao,
+                epPolicyTemplateDao, epForwardingTemplateDao);
+        epPolicyTemplateListener = new EPPolicyTemplateListenerImpl(dataBroker, sxpMapperReactor, epPolicyTemplateCachedDao,
+                masterDBBindingDao);
+        epForwardingTemplateListener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapperReactor, epForwardingTemplateCachedDao,
+                masterDBBindingDao);
+        LOG.info("started SxmMapper");
+    }
+
+    // register listeners to ip/sgt and EP-templates (by SGT, by subnet) -> 3x
+    // exclusively write L3-EP to DS upon DataChangeEvent
+
+    @Override
+    public void close() throws Exception {
+        //TODO: stub
+        sxpDatabaseListener.close();
+        epPolicyTemplateListener.close();
+        epForwardingTemplateListener.close();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImpl.java
new file mode 100644 (file)
index 0000000..8ed0329
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
+
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Purpose: exclusively processes sxp master database changes and EGP templates changes
+ */
+public class SxpMapperReactorImpl implements SxpMapperReactor {
+    private final EndpointService l3EndpointService;
+
+    public SxpMapperReactorImpl(final EndpointService l3EndpointService) {
+        this.l3EndpointService = l3EndpointService;
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<Void>> processPolicyAndSxpMasterDB(final EndpointPolicyTemplateBySgt template, final MasterDatabaseBinding masterDatabaseBinding) {
+        // apply sxpMasterDB to policy template
+        final RegisterEndpointInput input = new RegisterEndpointInputBuilder()
+                .setCondition(template.getConditions())
+                .setTenant(template.getTenant())
+                .setEndpointGroups(template.getEndpointGroups())
+                .build();
+
+        // invoke service
+        return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(input));
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<Void>> processForwardingAndSxpMasterDB(final EndpointForwardingTemplateBySubnet template, final MasterDatabaseBinding masterDatabaseBinding) {
+        // apply sxpMasterDB to policy template
+        final RegisterEndpointInput input = new RegisterEndpointInputBuilder()
+                .setNetworkContainment(template.getNetworkContainment())
+                .build();
+
+        // invoke service
+        return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(input));
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImpl.java
new file mode 100644 (file)
index 0000000..65ce34e
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Purpose: general dao for EndPoint templates
+ */
+public class EPForwardingTemplateDaoImpl implements DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> {
+
+    public static final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent());
+    private final DataBroker dataBroker;
+    private final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> cachedDao;
+
+    public EPForwardingTemplateDaoImpl(final DataBroker dataBroker,
+                                       final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> cachedDao) {
+        this.dataBroker = dataBroker;
+        this.cachedDao = cachedDao;
+    }
+
+    @Override
+    public ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> read(@Nonnull final IpPrefix key) {
+        final Optional<EndpointForwardingTemplateBySubnet> value = lookup(cachedDao, key);
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> readResult;
+        if (value.isPresent()) {
+            readResult = Futures.immediateFuture(value);
+        } else if (!cachedDao.isEmpty()) {
+            return READ_FUTURE_ABSENT;
+        } else {
+            final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+            final CheckedFuture<Optional<SxpMapper>, ReadFailedException> read =
+                    rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(key));
+
+            Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
+
+            readResult = Futures.transform(read, new Function<Optional<SxpMapper>, Optional<EndpointForwardingTemplateBySubnet>>() {
+                @Nullable
+                @Override
+                public Optional<EndpointForwardingTemplateBySubnet> apply(@Nullable final Optional<SxpMapper> input) {
+                    if (input.isPresent()) {
+                        // clean cache
+                        cachedDao.invalidateCache();
+
+                        // iterate through all template entries and update cachedDao
+                        final List<EndpointForwardingTemplateBySubnet> templateLot = input.get().getEndpointForwardingTemplateBySubnet();
+                        if (templateLot != null) {
+                            for (EndpointForwardingTemplateBySubnet template : templateLot) {
+                                cachedDao.update(template.getIpPrefix(), template);
+                            }
+                        }
+                        return cachedDao.find(key);
+                    } else {
+                        return Optional.absent();
+                    }
+                }
+            });
+        }
+        return readResult;
+    }
+
+    protected InstanceIdentifier<SxpMapper> buildReadPath(final IpPrefix key) {
+        return EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH;
+    }
+
+    private Optional<EndpointForwardingTemplateBySubnet> lookup(final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> cachedDao, final IpPrefix key) {
+        return cachedDao.find(key);
+    }
+
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImpl.java
new file mode 100644 (file)
index 0000000..de2f60f
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Purpose: general dao for EndPoint templates
+ */
+public class EPPolicyTemplateDaoImpl implements DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> {
+
+    private final DataBroker dataBroker;
+    private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao;
+
+    public EPPolicyTemplateDaoImpl(final DataBroker dataBroker,
+                                   final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao) {
+        this.dataBroker = dataBroker;
+        this.cachedDao = cachedDao;
+    }
+
+    @Override
+    public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read(@Nonnull final Sgt key) {
+        final Optional<EndpointPolicyTemplateBySgt> cachedEndpointPolicyTemplateBySgtalue = lookup(cachedDao, key);
+        if (cachedEndpointPolicyTemplateBySgtalue.isPresent()) {
+            return Futures.immediateFuture(cachedEndpointPolicyTemplateBySgtalue);
+        } else {
+            final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+            final CheckedFuture<Optional<EndpointPolicyTemplateBySgt>, ReadFailedException> read =
+                    rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(key));
+
+            Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
+
+            return Futures.transform(read, new Function<Optional<EndpointPolicyTemplateBySgt>, Optional<EndpointPolicyTemplateBySgt>>() {
+                @Nullable
+                @Override
+                public Optional<EndpointPolicyTemplateBySgt> apply(@Nullable final Optional<EndpointPolicyTemplateBySgt> input) {
+                    if (input.isPresent()) {
+                        cachedDao.update(key, input.get());
+                    }
+                    return input;
+                }
+            });
+        }
+    }
+
+    protected InstanceIdentifier<EndpointPolicyTemplateBySgt> buildReadPath(final Sgt key) {
+        return EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH
+                .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(key));
+    }
+
+    private Optional<EndpointPolicyTemplateBySgt> lookup(final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao, final Sgt key) {
+        return cachedDao.find(key);
+    }
+
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImpl.java
new file mode 100644 (file)
index 0000000..e2bf499
--- /dev/null
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: general dao for EndPoint templates
+ */
+public class MasterDatabaseBindingDaoImpl implements DSAsyncDao<IpPrefix, MasterDatabaseBinding>,
+        ReadableByKey<Sgt, MasterDatabaseBinding> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingDaoImpl.class);
+
+    private final DataBroker dataBroker;
+    private final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> cachedDao;
+
+    public MasterDatabaseBindingDaoImpl(final DataBroker dataBroker,
+                              final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> cachedDao) {
+        this.dataBroker = dataBroker;
+        this.cachedDao = cachedDao;
+    }
+
+    @Override
+    public ListenableFuture<Optional<MasterDatabaseBinding>> read(@Nonnull final IpPrefix key) {
+        final Optional<MasterDatabaseBinding> cachedMasterDatabaseBinding = lookup(cachedDao, key);
+        if (cachedMasterDatabaseBinding.isPresent()) {
+            return Futures.immediateFuture(cachedMasterDatabaseBinding);
+        } else {
+            final ListenableFuture<Void> cacheUpdatedFt = updateCache();
+
+            return Futures.transform(cacheUpdatedFt, new Function<Void, Optional<MasterDatabaseBinding>>() {
+                @Nullable
+                @Override
+                public Optional<MasterDatabaseBinding> apply(@Nullable final Void input) {
+                    return lookup(cachedDao, key);
+                }
+            });
+        }
+    }
+
+    private ListenableFuture<Void> updateCache() {
+        final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        final CheckedFuture<Optional<Topology>, ReadFailedException> read =
+                rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(null));
+
+        Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
+
+        return Futures.transform(read, new Function<Optional<Topology>, Void>() {
+            @Nullable
+            @Override
+            public Void apply(@Nullable final Optional<Topology> input) {
+                if (input.isPresent()) {
+                    // clean cache
+                    cachedDao.invalidateCache();
+
+                    for (Node node : input.get().getNode()) {
+                        final SxpNodeIdentity sxpNodeIdentity = node.getAugmentation(SxpNodeIdentity.class);
+                        if (sxpNodeIdentity != null) {
+                            final List<MasterDatabaseBinding> masterDBBindings = sxpNodeIdentity.getMasterDatabase().getMasterDatabaseBinding();
+                            if (masterDBBindings != null) {
+                                for (MasterDatabaseBinding masterDBItem : masterDBBindings) {
+                                    // update all
+                                    final MasterDatabaseBinding previousValue = cachedDao.update(
+                                            masterDBItem.getIpPrefix(), masterDBItem);
+                                    if (previousValue != null) {
+                                        LOG.warn("updated key already obtained: [node:{}, sgt:{}]",
+                                                node.getNodeId().getValue(),
+                                                masterDBItem.getSecurityGroupTag());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    LOG.warn("failed to update cache of SxpMasterDB - no data");
+                }
+                return null;
+            }
+        });
+    }
+
+    private InstanceIdentifier<Topology> buildReadPath(final Sgt key) {
+        return MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH;
+    }
+
+    private Optional<MasterDatabaseBinding> lookup(final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> cachedDao, final IpPrefix key) {
+        return cachedDao.find(key);
+    }
+
+    @Override
+    public ListenableFuture<Collection<MasterDatabaseBinding>> readBy(@Nonnull final Sgt specialKey) {
+        final ListenableFuture<Void> cacheUpdatedFt;
+        if (!cachedDao.isEmpty()) {
+            cacheUpdatedFt = Futures.immediateFuture(null);
+        } else {
+            cacheUpdatedFt = updateCache();
+        }
+
+        return Futures.transform(cacheUpdatedFt, new Function<Void, Collection<MasterDatabaseBinding>>() {
+            @Nullable
+            @Override
+            public Collection<MasterDatabaseBinding> apply(@Nullable final Void input) {
+                final Collection<MasterDatabaseBinding> foundGroups = new ArrayList<>();
+
+                for (MasterDatabaseBinding masterDBItem : cachedDao.values()) {
+                    if (masterDBItem.getSecurityGroupTag().equals(specialKey)) {
+                        foundGroups.add(masterDBItem);
+                    }
+                }
+                return foundGroups;
+            }
+        });
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java
new file mode 100644 (file)
index 0000000..bf8471e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.ForwardingTemplateUtil;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SubnetInfoKeyDecorator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+
+/**
+ * Purpose: generic implementation of {@link SimpleCachedDao}
+ */
+public class SimpleCachedDaoEPForwardingTemplateImpl implements SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> {
+
+    private final ConcurrentMap<IpPrefix, EndpointForwardingTemplateBySubnet> plainCache;
+    private final ConcurrentMap<SubnetInfoKeyDecorator, EndpointForwardingTemplateBySubnet> subnetCache;
+    private final Pattern IP_MASK_EATER_RE = Pattern.compile("/[0-9]+");
+
+    public SimpleCachedDaoEPForwardingTemplateImpl() {
+        plainCache = new ConcurrentHashMap<>();
+        subnetCache = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public EndpointForwardingTemplateBySubnet update(@Nonnull final IpPrefix key, @Nullable final EndpointForwardingTemplateBySubnet value) {
+        final EndpointForwardingTemplateBySubnet previousValue;
+        if (ForwardingTemplateUtil.isPlain(key)) {
+            previousValue = updatePlainCache(key, value);
+        } else {
+            previousValue = updateSubnetCache(key, value);
+        }
+
+        return previousValue;
+    }
+
+    private EndpointForwardingTemplateBySubnet updateSubnetCache(final IpPrefix key, final EndpointForwardingTemplateBySubnet value) {
+        final EndpointForwardingTemplateBySubnet previousValue;
+        final SubnetInfoKeyDecorator subnetKey = ForwardingTemplateUtil.buildSubnetInfoKey(key);
+        if (value != null) {
+            previousValue = subnetCache.put(subnetKey, value);
+        } else {
+            previousValue = subnetCache.remove(subnetKey);
+        }
+        return previousValue;
+    }
+
+    private EndpointForwardingTemplateBySubnet updatePlainCache(final @Nonnull IpPrefix key, final @Nullable EndpointForwardingTemplateBySubnet value) {
+        final EndpointForwardingTemplateBySubnet previousValue;
+        if (value != null) {
+            previousValue = plainCache.put(key, value);
+        } else {
+            previousValue = plainCache.remove(key);
+        }
+        return previousValue;
+    }
+
+    @Override
+    public Optional<EndpointForwardingTemplateBySubnet> find(@Nonnull final IpPrefix key) {
+        final Optional<EndpointForwardingTemplateBySubnet> template;
+        if (ForwardingTemplateUtil.isPlain(key)) {
+            final Optional<EndpointForwardingTemplateBySubnet> fastPlain = Optional.fromNullable(plainCache.get(key));
+            if (fastPlain.isPresent()) {
+                template = fastPlain;
+            } else {
+                template = lookupSlowSubnet(key.getIpv4Prefix().getValue());
+            }
+        } else {
+            final SubnetInfoKeyDecorator keyDecorator = ForwardingTemplateUtil.buildSubnetInfoKey(key);
+            final Optional<EndpointForwardingTemplateBySubnet> fastSubnet =
+                    Optional.fromNullable(subnetCache.get(keyDecorator));
+            if (fastSubnet.isPresent()) {
+                template = fastSubnet;
+            } else {
+                template = Optional.absent();
+            }
+        }
+        return template;
+    }
+
+    private Optional<EndpointForwardingTemplateBySubnet> lookupSlowSubnet(final String value) {
+        final String plainIp = IP_MASK_EATER_RE.matcher(value).replaceFirst("");
+        EndpointForwardingTemplateBySubnet valueCandidate = null;
+        int addressCount = 0;
+        for (Map.Entry<SubnetInfoKeyDecorator, EndpointForwardingTemplateBySubnet> entry : subnetCache.entrySet()) {
+            final SubnetUtils.SubnetInfo subnetInfo = entry.getKey().getDelegate();
+            if (subnetInfo.isInRange(plainIp)) {
+                final int addressCountTmp = subnetInfo.getAddressCount();
+                if (valueCandidate == null || addressCount > addressCountTmp) {
+                    valueCandidate = entry.getValue();
+                    addressCount = addressCountTmp;
+                }
+            }
+        }
+        return Optional.fromNullable(valueCandidate);
+    }
+
+    @Override
+    public void invalidateCache() {
+        plainCache.clear();
+        subnetCache.clear();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return plainCache.isEmpty() && subnetCache.isEmpty();
+    }
+
+    @Override
+    public Iterable<EndpointForwardingTemplateBySubnet> values() {
+        return Iterables.unmodifiableIterable(Iterables.concat(plainCache.values(), subnetCache.values()));
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImpl.java
new file mode 100644 (file)
index 0000000..b57ac74
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Purpose: generic implementation of {@link SimpleCachedDao}
+ */
+public class SimpleCachedDaoImpl<K, V extends DataObject> implements SimpleCachedDao<K, V> {
+
+    private final ConcurrentMap<K, V> cache;
+
+    public SimpleCachedDaoImpl() {
+        cache = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public V update(@Nonnull final K key, @Nullable final V value) {
+        final V previousValue;
+        if (value != null) {
+            previousValue = cache.put(key, value);
+        } else {
+            previousValue = cache.remove(key);
+        }
+
+        return previousValue;
+    }
+
+    @Override
+    public Optional<V> find(@Nonnull final K key) {
+        return Optional.fromNullable(cache.get(key));
+    }
+
+    @Override
+    public void invalidateCache() {
+        cache.clear();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return cache.isEmpty();
+    }
+
+    @Override
+    public Iterable<V> values() {
+        return Iterables.unmodifiableIterable(cache.values());
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImpl.java
new file mode 100644 (file)
index 0000000..83d021a
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: listens to EP forwarding template and propagates change events for further processing
+ */
+public class EPForwardingTemplateListenerImpl implements EPTemplateListener<EndpointForwardingTemplateBySubnet> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EPForwardingTemplateListenerImpl.class);
+
+    public static final FutureCallback<RpcResult<Void>> ANY_RPC_FUTURE_CALLBACK =
+            L3EPServiceUtil.createFailureLoggingCallback("failed to read epForwardingTemplate");
+
+    private final SxpMapperReactor sxpMapperReactor;
+    private final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> templateCachedDao;
+    private final DSAsyncDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDao;
+    private final ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    private final InstanceIdentifier<EndpointForwardingTemplateBySubnet> templatePath;
+
+    public EPForwardingTemplateListenerImpl(final DataBroker dataBroker,
+                                            final SxpMapperReactor sxpMapperReactor,
+                                            final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> templateCachedDao,
+                                            final DSAsyncDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDao) {
+        this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
+        this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao);
+        this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao);
+        templatePath = EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH.child(EndpointForwardingTemplateBySubnet.class);
+
+        final DataTreeIdentifier<EndpointForwardingTemplateBySubnet> dataTreeIdentifier = new DataTreeIdentifier<>(
+                LogicalDatastoreType.CONFIGURATION, templatePath);
+        listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this);
+        LOG.debug("started listening to {}", templatePath);
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<EndpointForwardingTemplateBySubnet>> collection) {
+        for (DataTreeModification<EndpointForwardingTemplateBySubnet> change : collection) {
+            LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType());
+            // update cached dao
+            final InstanceIdentifier<EndpointForwardingTemplateBySubnet> changePath = change.getRootPath().getRootIdentifier();
+            final IpPrefix changeKey = changePath.firstKeyOf(EndpointForwardingTemplateBySubnet.class).getIpPrefix();
+            SxpListenerUtil.updateCachedDao(templateCachedDao, changeKey, change);
+
+            final EndpointForwardingTemplateBySubnet epForwardingTemplate = change.getRootNode().getDataAfter();
+            processWithSxpMasterDB(changeKey, epForwardingTemplate);
+        }
+    }
+
+    private void processWithSxpMasterDB(final IpPrefix changeKey, final EndpointForwardingTemplateBySubnet epForwardingTemplate) {
+        final ListenableFuture<Optional<MasterDatabaseBinding>> sxpMasterDbItemFuture = masterDBBindingDao.read(changeKey);
+
+        final ListenableFuture<RpcResult<Void>> allRpcResult = Futures.transform(sxpMasterDbItemFuture, new AsyncFunction<Optional<MasterDatabaseBinding>, RpcResult<Void>>() {
+            @Override
+            public ListenableFuture<RpcResult<Void>> apply(final Optional<MasterDatabaseBinding> input) throws Exception {
+                if (input == null && input.isPresent()) {
+                    LOG.debug("no epForwardingTemplate available for sgt: {}", changeKey);
+                    throw new IllegalArgumentException("no epForwardingTemplate available");
+                } else {
+                    List<ListenableFuture<RpcResult<Void>>> resultBag = new ArrayList<>();
+                    LOG.trace("processing sxpMasterDB event and epForwardingTemplate for sgt: {}", changeKey);
+                    final ListenableFuture<RpcResult<Void>> rpcResult = sxpMapperReactor.processForwardingAndSxpMasterDB(epForwardingTemplate, input.get());
+                    return rpcResult;
+                }
+            }
+        });
+
+        Futures.addCallback(allRpcResult, ANY_RPC_FUTURE_CALLBACK);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.debug("closing listener registration to {}", templatePath);
+        listenerRegistration.close();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImpl.java
new file mode 100644 (file)
index 0000000..6bd4a9d
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: listens to EP policy template and propagates change events for further processing
+ */
+public class EPPolicyTemplateListenerImpl implements EPTemplateListener<EndpointPolicyTemplateBySgt> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EPPolicyTemplateListenerImpl.class);
+
+    private static final FutureCallback<List<RpcResult<Void>>> RPC_RESULT_FUTURE_CALLBACK =
+            L3EPServiceUtil.createFailureLoggingCallback("failed to apply epPolicyTemplate");
+
+    private final ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    private final InstanceIdentifier<EndpointPolicyTemplateBySgt> templatePath;
+    private final SxpMapperReactor sxpMapperReactor;
+    private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> templateCachedDao;
+    private final ReadableByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao;
+
+    public EPPolicyTemplateListenerImpl(final DataBroker dataBroker,
+                                        final SxpMapperReactor sxpMapperReactor,
+                                        final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> templateCachedDao,
+                                        final ReadableByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao) {
+        this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
+        this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao);
+        this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao);
+        templatePath = EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH.child(EndpointPolicyTemplateBySgt.class);
+
+        final DataTreeIdentifier<EndpointPolicyTemplateBySgt> dataTreeIdentifier = new DataTreeIdentifier<>(
+                LogicalDatastoreType.CONFIGURATION, templatePath);
+        listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this);
+        LOG.debug("started listening to {}", templatePath);
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<EndpointPolicyTemplateBySgt>> collection) {
+        for (DataTreeModification<EndpointPolicyTemplateBySgt> change : collection) {
+            LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType());
+
+            // update cached dao
+            final InstanceIdentifier<EndpointPolicyTemplateBySgt> changePath = change.getRootPath().getRootIdentifier();
+            final Sgt changeKey = changePath.firstKeyOf(EndpointPolicyTemplateBySgt.class).getSgt();
+            SxpListenerUtil.updateCachedDao(templateCachedDao, changeKey, change);
+
+            final EndpointPolicyTemplateBySgt epPolicyTemplate = change.getRootNode().getDataAfter();
+            processWithSxpMasterDB(changeKey, epPolicyTemplate);
+        }
+    }
+
+    private void processWithSxpMasterDB(final Sgt changeKey, final EndpointPolicyTemplateBySgt epPolicyTemplate) {
+        final ListenableFuture<Collection<MasterDatabaseBinding>> sxpMasterDbItemFuture = masterDBBindingDao.readBy(changeKey);
+        final ListenableFuture<List<RpcResult<Void>>> rpcResult = Futures.transform(sxpMasterDbItemFuture, new AsyncFunction<Collection<MasterDatabaseBinding>, List<RpcResult<Void>>>() {
+            @Override
+            public ListenableFuture<List<RpcResult<Void>>> apply(final Collection<MasterDatabaseBinding> input) throws Exception {
+                if (input == null || input.isEmpty()) {
+                    LOG.debug("no epPolicyTemplate available from sgt: {}", changeKey);
+                    throw new IllegalArgumentException("no epPolicyTemplate available");
+                } else {
+                    LOG.trace("processing sxpMasterDB event and epPolicyTemplate for sgt: {}", changeKey);
+                    List<ListenableFuture<RpcResult<Void>>> allResults = new ArrayList<>(input.size());
+                    for (MasterDatabaseBinding masterDBItem : input) {
+                            allResults.add(sxpMapperReactor.processPolicyAndSxpMasterDB(epPolicyTemplate, masterDBItem));
+                    }
+                    return Futures.successfulAsList(allResults);
+                }
+            }
+        });
+
+        Futures.addCallback(rpcResult, RPC_RESULT_FUTURE_CALLBACK);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.debug("closing listener registration to {}", templatePath);
+        listenerRegistration.close();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImpl.java
new file mode 100644 (file)
index 0000000..7a03b45
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * listens to sxp master database and propagates change events for further processing
+ */
+public class MasterDatabaseBindingListenerImpl implements MasterDatabaseBindingListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingListenerImpl.class);
+
+    private static final FutureCallback<RpcResult<Void>> RPC_POLICY_RESULT_FUTURE_CALLBACK =
+            L3EPServiceUtil.createFailureLoggingCallback("failed to read epPolicyTemplate");
+
+    public static final FutureCallback<RpcResult<Void>> RPC_FW_RESULT_FUTURE_CALLBACK =
+            L3EPServiceUtil.createFailureLoggingCallback("failed to read epForwardingTemplate");
+
+    private final SxpMapperReactor sxpMapperReactor;
+    private final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDaoCached;
+    private final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+    private final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
+
+    private final ListenerRegistration<? extends DataTreeChangeListener> listenerRegistration;
+    private final InstanceIdentifier<MasterDatabaseBinding> sxpDbPath;
+
+    public MasterDatabaseBindingListenerImpl(final DataBroker dataBroker,
+                                             final SxpMapperReactor sxpMapperReactor,
+                                             final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDaoCached,
+                                             final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao,
+                                             final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao) {
+        this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
+        this.masterDBBindingDaoCached = Preconditions.checkNotNull(masterDBBindingDaoCached);
+        this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao);
+        this.epForwardingTemplateDao = Preconditions.checkNotNull(epForwardingTemplateDao);
+        sxpDbPath = MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH
+                .child(Node.class)
+                .augmentation(SxpNodeIdentity.class)
+                .child(MasterDatabase.class)
+                .child(MasterDatabaseBinding.class);
+
+        final DataTreeIdentifier<MasterDatabaseBinding> dataTreeIdentifier = new DataTreeIdentifier<>(
+                LogicalDatastoreType.OPERATIONAL, sxpDbPath);
+        listenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, this);
+        LOG.debug("started listening to {}", sxpDbPath);
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<MasterDatabaseBinding>> collection) {
+        for (DataTreeModification<MasterDatabaseBinding> change : collection) {
+            LOG.trace("received modification: {} -> {}", change.getRootPath(), change.getRootNode().getModificationType());
+            // update cached dao
+            final MasterDatabaseBinding sxpMasterDBItem = change.getRootNode().getDataAfter();
+            if (sxpMasterDBItem == null) {
+                //TODO: cover sgt-ip mapping removal
+            } else {
+                final Sgt sgtKey = sxpMasterDBItem.getSecurityGroupTag();
+                final IpPrefix ipPrefixKey = sxpMasterDBItem.getIpPrefix();
+                SxpListenerUtil.updateCachedDao(masterDBBindingDaoCached, ipPrefixKey, change);
+
+                processWithEPPolicyTemplate(sgtKey, sxpMasterDBItem);
+                processWithEPForwardingTemplate(ipPrefixKey, sxpMasterDBItem);
+            }
+        }
+    }
+
+    private void processWithEPForwardingTemplate(final IpPrefix changeKey, final MasterDatabaseBinding sxpMasterDBItem) {
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> epForwardingTemplateFuture =
+                epForwardingTemplateDao.read(changeKey);
+
+        final ListenableFuture<RpcResult<Void>> rpcResult = Futures.transform(epForwardingTemplateFuture, new AsyncFunction<Optional<EndpointForwardingTemplateBySubnet>, RpcResult<Void>>() {
+            @Override
+            public ListenableFuture<RpcResult<Void>> apply(final Optional<EndpointForwardingTemplateBySubnet> input) throws Exception {
+                if (input == null || !input.isPresent()) {
+                    LOG.debug("no epForwardingTemplate available for ipPrefix: {}", changeKey);
+                    throw new IllegalArgumentException("no epForwardingTemplate available");
+                } else {
+                    LOG.trace("processing sxpMasterDB event and epForwardingTemplate for ip-prefix: {}", changeKey);
+                    return sxpMapperReactor.processForwardingAndSxpMasterDB(input.get(), sxpMasterDBItem);
+                }
+            }
+        });
+        Futures.addCallback(rpcResult, RPC_FW_RESULT_FUTURE_CALLBACK);
+    }
+
+    private void processWithEPPolicyTemplate(final Sgt changeKey, final MasterDatabaseBinding sxpMasterDBItem) {
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> epPolicyTemplateFuture =
+                epPolicyTemplateDao.read(changeKey);
+
+        final ListenableFuture<RpcResult<Void>> rpcResult = Futures.transform(epPolicyTemplateFuture, new AsyncFunction<Optional<EndpointPolicyTemplateBySgt>, RpcResult<Void>>() {
+            @Override
+            public ListenableFuture<RpcResult<Void>> apply(final Optional<EndpointPolicyTemplateBySgt> input) throws Exception {
+                if (input == null || !input.isPresent()) {
+                    LOG.debug("no epPolicyTemplate available for sgt: {}", changeKey);
+                    throw new IllegalArgumentException("no epPolicyTemplate available");
+                } else {
+                    LOG.trace("processing sxpMasterDB event and epPolicyTemplate for sgt: {}", changeKey);
+                    return sxpMapperReactor.processPolicyAndSxpMasterDB(input.get(), sxpMasterDBItem);
+                }
+            }
+        });
+
+        Futures.addCallback(rpcResult, RPC_POLICY_RESULT_FUTURE_CALLBACK);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.debug("closing listener registration to {}", sxpDbPath);
+        listenerRegistration.close();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtil.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtil.java
new file mode 100644 (file)
index 0000000..e513e42
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import javax.annotation.Nonnull;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+
+/**
+ * Purpose: util methods for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet}
+ */
+public final class ForwardingTemplateUtil {
+
+    public static final String FULL_IPV4_MASK_SUFFIX = "/32";
+
+    private ForwardingTemplateUtil() {
+        throw new IllegalAccessError("constructing util class");
+    }
+
+    public static boolean isPlain(final IpPrefix key) {
+        return key.getIpv4Prefix().getValue().endsWith(FULL_IPV4_MASK_SUFFIX);
+    }
+
+    public static SubnetInfoKeyDecorator buildSubnetInfoKey(@Nonnull final IpPrefix value) {
+        return new SubnetInfoKeyDecorator(new SubnetUtils(value.getIpv4Prefix().getValue()).getInfo());
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandDirectImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandDirectImpl.java
new file mode 100644 (file)
index 0000000..6538124
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.IpPrefixEqualCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+
+/**
+ * Purpose: provide simple equal using direct invocation of {@link Object#equals(Object)} method
+ */
+public class IpPrefixEqualCommandDirectImpl implements IpPrefixEqualCommand {
+    private final IpPrefix myValue;
+
+    public IpPrefixEqualCommandDirectImpl(@Nonnull final IpPrefix myValue) {
+        this.myValue = myValue;
+    }
+
+    @Override
+    public boolean isEqualTo(final IpPrefix value) {
+        return myValue.equals(value);
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandSubnetImpl.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/IpPrefixEqualCommandSubnetImpl.java
new file mode 100644 (file)
index 0000000..e6442a8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import javax.annotation.Nonnull;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.IpPrefixEqualCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+
+/**
+ * Purpose: provide equal using {@link SubnetUtils.SubnetInfo#isInRange(String)} method
+ */
+public class IpPrefixEqualCommandSubnetImpl implements IpPrefixEqualCommand {
+    private final SubnetUtils.SubnetInfo myValue;
+
+    public IpPrefixEqualCommandSubnetImpl(@Nonnull final IpPrefix myValue) {
+        this.myValue = new SubnetUtils(stripToCidr(myValue)).getInfo();
+    }
+
+    @Override
+    public boolean isEqualTo(final IpPrefix value) {
+        return myValue.isInRange(stripToCidr(value));
+    }
+
+    private String stripToCidr(final IpPrefix value) {
+        return value.getIpv4Prefix().getValue();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/L3EPServiceUtil.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/L3EPServiceUtil.java
new file mode 100644 (file)
index 0000000..622f747
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import com.google.common.util.concurrent.FutureCallback;
+import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: TODO!
+ */
+public final class L3EPServiceUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(L3EPServiceUtil.class);
+
+    private L3EPServiceUtil() {
+        throw new IllegalAccessError("constructing util class");
+    }
+
+    public static <O> FutureCallback<O> createFailureLoggingCallback(final String failMessage) {
+        return new FutureCallback<O>() {
+            @Override
+            public void onSuccess(@Nullable final O result) {
+                // NOOP
+            }
+
+            @Override
+            public void onFailure(final Throwable t) {
+                LOG.warn(failMessage, t);
+            }
+        };
+    }
+
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SubnetInfoKeyDecorator.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SubnetInfoKeyDecorator.java
new file mode 100644 (file)
index 0000000..3fae07e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import org.apache.commons.net.util.SubnetUtils;
+
+/**
+ * Purpose: wraps {@link SubnetUtils.SubnetInfo} and overwrites hashcode and equals methods in order to
+ * be applicable as map key
+ *
+ */
+public class SubnetInfoKeyDecorator {
+
+    private final SubnetUtils.SubnetInfo delegate;
+
+    public SubnetInfoKeyDecorator(final SubnetUtils.SubnetInfo delegate) {
+        this.delegate = delegate;
+    }
+
+    public SubnetUtils.SubnetInfo getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        final SubnetInfoKeyDecorator that = (SubnetInfoKeyDecorator) o;
+
+        return delegate.getCidrSignature().equals(that.delegate.getCidrSignature());
+
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate.getCidrSignature().hashCode();
+    }
+}
diff --git a/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SxpListenerUtil.java b/sxp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/SxpListenerUtil.java
new file mode 100644 (file)
index 0000000..de874fc
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Purpose: provide general logic used by listeners
+ */
+public final class SxpListenerUtil {
+
+    private SxpListenerUtil() {
+        throw new IllegalAccessError("constructing util class");
+    }
+
+
+    public static <K, V extends DataObject> void updateCachedDao(final SimpleCachedDao<K, V> valueCachedDao,
+                                                                 final K key,
+                                                                 final DataTreeModification<V> change) {
+        final V value = change.getRootNode().getDataAfter();
+        valueCachedDao.update(key, value);
+    }
+
+    public static FutureCallback<Optional<?>> createTxCloseCallback(final ReadOnlyTransaction rTx) {
+        return new FutureCallback<Optional<?>>() {
+            @Override
+            public void onSuccess(@Nullable final Optional<?> result) {
+                rTx.close();
+            }
+
+            @Override
+            public void onFailure(final Throwable t) {
+                rTx.close();
+            }
+        };
+    }
+}
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/SxpMapperReactorImplTest.java
new file mode 100644 (file)
index 0000000..3c7af75
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link SxpMapperReactorImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SxpMapperReactorImplTest {
+
+    @Mock
+    private EndpointService l3EndpointService;
+    @Mock
+    private EndpointPolicyTemplateBySgt epPolicyTemplate;
+    @Mock
+    private MasterDatabaseBinding masterDBBinding;
+    @Mock
+    private EndpointForwardingTemplateBySubnet epForwardingTemplate;
+
+    private SxpMapperReactorImpl sxpMapperReactor;
+
+    @Before
+    public void setUp() throws Exception {
+        sxpMapperReactor = new SxpMapperReactorImpl(l3EndpointService);
+        Mockito.when(l3EndpointService.registerEndpoint(Matchers.<RegisterEndpointInput>any()))
+                .thenReturn(RpcResultBuilder.<Void>success().buildFuture());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        Mockito.verifyNoMoreInteractions(l3EndpointService);
+    }
+
+    @Test
+    public void testProcessPolicyAndSxpMasterDB() throws Exception {
+        sxpMapperReactor.processPolicyAndSxpMasterDB(epPolicyTemplate, masterDBBinding);
+        Mockito.verify(l3EndpointService).registerEndpoint(Matchers.<RegisterEndpointInput>any());
+    }
+
+    @Test
+    public void testProcessForwardingAndSxpMasterDB() throws Exception {
+        sxpMapperReactor.processForwardingAndSxpMasterDB(epForwardingTemplate, masterDBBinding);
+        Mockito.verify(l3EndpointService).registerEndpoint(Matchers.<RegisterEndpointInput>any());
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPForwardingTemplateDaoImplTest.java
new file mode 100644 (file)
index 0000000..e1ee8a2
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapperBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link EPForwardingTemplateDaoImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EPForwardingTemplateDaoImplTest {
+
+    public static final InstanceIdentifier<SxpMapper> SXP_MAPPER_PATH = InstanceIdentifier.create(SxpMapper.class);
+    private static final IpPrefix KEY_1 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+    private final SxpMapper SXP_MAPPER_VALUE;
+    private final EndpointForwardingTemplateBySubnet EP_FW_TEMPLATE_VALUE;
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> cachedDao;
+    @Mock
+    private ReadOnlyTransaction rTx;
+
+    private EPForwardingTemplateDaoImpl dao;
+
+    public EPForwardingTemplateDaoImplTest() {
+        EP_FW_TEMPLATE_VALUE = new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(KEY_1)
+                .build();
+        SXP_MAPPER_VALUE = new SxpMapperBuilder()
+                .setEndpointForwardingTemplateBySubnet(Lists.newArrayList(EP_FW_TEMPLATE_VALUE))
+                .build();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        dao = new EPForwardingTemplateDaoImpl(dataBroker, cachedDao);
+    }
+
+    @Test
+    public void testRead_absent() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(Optional.<EndpointForwardingTemplateBySubnet>absent());
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<SxpMapper>>any())).thenReturn(
+                Futures.<Optional<SxpMapper>, ReadFailedException>immediateCheckedFuture(Optional.<SxpMapper>absent()));
+
+
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertFalse(read.get().isPresent());
+    }
+
+    @Test
+    public void testRead_presentCached() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(Optional.of(EP_FW_TEMPLATE_VALUE));
+
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getIpPrefix());
+    }
+
+    @Test
+    public void testRead_presentDS() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(
+                Optional.<EndpointForwardingTemplateBySubnet>absent(),
+                Optional.of(EP_FW_TEMPLATE_VALUE));
+        Mockito.when(cachedDao.isEmpty()).thenReturn(true, false);
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<SxpMapper>>any())).thenReturn(
+                Futures.<Optional<SxpMapper>, ReadFailedException>immediateCheckedFuture(Optional.of(SXP_MAPPER_VALUE)));
+
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getIpPrefix());
+
+        final InOrder inOrder = Mockito.inOrder(cachedDao);
+        inOrder.verify(cachedDao).invalidateCache();
+        inOrder.verify(cachedDao).update(KEY_1, EP_FW_TEMPLATE_VALUE);
+        inOrder.verify(cachedDao).find(KEY_1);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testBuildReadPath() throws Exception {
+        final InstanceIdentifier<SxpMapper> readPath = dao.buildReadPath(KEY_1);
+        Assert.assertEquals(SXP_MAPPER_PATH, readPath);
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/EPPolicyTemplateDaoImplTest.java
new file mode 100644 (file)
index 0000000..a15a98b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.SxpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Test for {@link EPPolicyTemplateDaoImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EPPolicyTemplateDaoImplTest {
+
+    private static final Sgt KEY_1 = new Sgt(1);
+    private final EndpointPolicyTemplateBySgt EP_POLICY_TEMPLATE_VALUE;
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao;
+    @Mock
+    private ReadOnlyTransaction rTx;
+
+    private EPPolicyTemplateDaoImpl dao;
+
+    public EPPolicyTemplateDaoImplTest() {
+        EP_POLICY_TEMPLATE_VALUE = new EndpointPolicyTemplateBySgtBuilder()
+                .setSgt(KEY_1)
+                .build();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        dao = new EPPolicyTemplateDaoImpl(dataBroker, cachedDao);
+    }
+
+    @Test
+    public void testRead_absent() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<Sgt>any())).thenReturn(Optional.<EndpointPolicyTemplateBySgt>absent());
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<EndpointPolicyTemplateBySgt>>any())).thenReturn(
+                Futures.<Optional<EndpointPolicyTemplateBySgt>, ReadFailedException>immediateCheckedFuture(
+                        Optional.<EndpointPolicyTemplateBySgt>absent()));
+
+
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertFalse(read.get().isPresent());
+    }
+
+    @Test
+    public void testRead_presentCached() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<Sgt>any())).thenReturn(Optional.of(EP_POLICY_TEMPLATE_VALUE));
+
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getSgt());
+    }
+
+    @Test
+    public void testRead_presentDS() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<Sgt>any())).thenReturn(
+                Optional.<EndpointPolicyTemplateBySgt>absent());
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<EndpointPolicyTemplateBySgt>>any())).thenReturn(
+                Futures.<Optional<EndpointPolicyTemplateBySgt>, ReadFailedException>immediateCheckedFuture(
+                        Optional.of(EP_POLICY_TEMPLATE_VALUE)));
+
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read = dao.read(KEY_1);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getSgt());
+
+        final InOrder inOrder = Mockito.inOrder(cachedDao);
+        inOrder.verify(cachedDao).update(KEY_1, EP_POLICY_TEMPLATE_VALUE);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testBuildReadPath() throws Exception {
+        final KeyedInstanceIdentifier<EndpointPolicyTemplateBySgt, EndpointPolicyTemplateBySgtKey> expectedPath =
+                InstanceIdentifier.create(SxpMapper.class)
+                        .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(KEY_1));
+
+        final InstanceIdentifier<EndpointPolicyTemplateBySgt> readPath = dao.buildReadPath(KEY_1);
+        Assert.assertEquals(expectedPath, readPath);
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/MasterDatabaseBindingDaoImplTest.java
new file mode 100644 (file)
index 0000000..024e161
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.Collections;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.sxp.core.Configuration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link MasterDatabaseBindingDaoImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class MasterDatabaseBindingDaoImplTest {
+
+    private static final Sgt KEY_1 = new Sgt(1);
+    private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+    private final Topology TOPOLOGY_VALUE;
+    private final MasterDatabaseBinding MASTER_DB_BINDING_VALUE;
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SimpleCachedDao<IpPrefix, MasterDatabaseBinding> cachedDao;
+    @Mock
+    private ReadOnlyTransaction rTx;
+
+    private MasterDatabaseBindingDaoImpl dao;
+
+    public MasterDatabaseBindingDaoImplTest() {
+        MASTER_DB_BINDING_VALUE = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(KEY_1)
+                .setIpPrefix(IP_PREFIX)
+                .build();
+
+        TOPOLOGY_VALUE = new TopologyBuilder()
+                .setTopologyId(new TopologyId(Configuration.TOPOLOGY_NAME))
+                .setNode(Lists.newArrayList(new NodeBuilder()
+                        .setNodeId(new NodeId("utNodeId"))
+                        .addAugmentation(SxpNodeIdentity.class, new SxpNodeIdentityBuilder()
+                                .setMasterDatabase(new MasterDatabaseBuilder()
+                                        .setMasterDatabaseBinding(Lists.newArrayList(MASTER_DB_BINDING_VALUE))
+                                        .build())
+                                .build())
+                        .build()))
+                .build();
+    }
+
+
+    @Before
+    public void setUp() throws Exception {
+        dao = new MasterDatabaseBindingDaoImpl(dataBroker, cachedDao);
+    }
+
+    @Test
+    public void testRead_absent() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(Optional.<MasterDatabaseBinding>absent());
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<Topology>>any())).thenReturn(
+                Futures.<Optional<Topology>, ReadFailedException>immediateCheckedFuture(
+                        Optional.<Topology>absent()));
+
+
+        final ListenableFuture<Optional<MasterDatabaseBinding>> read = dao.read(IP_PREFIX);
+        Assert.assertTrue(read.isDone());
+        Assert.assertFalse(read.get().isPresent());
+    }
+
+    @Test
+    public void testRead_presentCached() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(Optional.of(MASTER_DB_BINDING_VALUE));
+
+        final ListenableFuture<Optional<MasterDatabaseBinding>> read = dao.read(IP_PREFIX);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getSecurityGroupTag());
+    }
+
+    @Test
+    public void testRead_presentDS() throws Exception {
+        Mockito.when(cachedDao.find(Matchers.<IpPrefix>any())).thenReturn(
+                Optional.<MasterDatabaseBinding>absent(),
+                Optional.of(MASTER_DB_BINDING_VALUE));
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
+                Matchers.<InstanceIdentifier<Topology>>any())).thenReturn(
+                Futures.<Optional<Topology>, ReadFailedException>immediateCheckedFuture(
+                        Optional.of(TOPOLOGY_VALUE)));
+
+        final ListenableFuture<Optional<MasterDatabaseBinding>> read = dao.read(IP_PREFIX);
+        Assert.assertTrue(read.isDone());
+        Assert.assertTrue(read.get().isPresent());
+        Assert.assertEquals(KEY_1, read.get().get().getSecurityGroupTag());
+
+        final InOrder inOrder = Mockito.inOrder(cachedDao);
+        inOrder.verify(cachedDao).invalidateCache();
+        inOrder.verify(cachedDao).update(IP_PREFIX, MASTER_DB_BINDING_VALUE);
+        inOrder.verify(cachedDao).find(IP_PREFIX);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testReadBy() throws Exception {
+        Mockito.when(cachedDao.isEmpty()).thenReturn(false);
+        Mockito.when(cachedDao.values()).thenReturn(Collections.singleton(MASTER_DB_BINDING_VALUE));
+
+        final ListenableFuture<Collection<MasterDatabaseBinding>> readByFt = dao.readBy(KEY_1);
+        Assert.assertTrue(readByFt.isDone());
+        Assert.assertEquals(1, readByFt.get().size());
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java
new file mode 100644 (file)
index 0000000..cddce65
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.collect.Iterables;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnetBuilder;
+
+/**
+ * Test for {@link SimpleCachedDaoEPForwardingTemplateImpl}.
+ */
+public class SimpleCachedDaoEPForwardingTemplateImplTest {
+
+    private static final IpPrefix IP_PREFIX_1 = buildIpPrefix("1.2.3.0/24");
+
+
+    private static final IpPrefix IP_PREFIX_2 = buildIpPrefix("1.2.3.4/32");
+
+    private SimpleCachedDaoEPForwardingTemplateImpl dao;
+
+    @Before
+    public void setUp() throws Exception {
+        dao = new SimpleCachedDaoEPForwardingTemplateImpl();
+        Assert.assertTrue(dao.isEmpty());
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        dao.update(IP_PREFIX_1, buildValue(IP_PREFIX_1));
+        dao.update(IP_PREFIX_2, buildValue(IP_PREFIX_2));
+
+        Assert.assertEquals(2, Iterables.size(dao.values()));
+    }
+
+    private EndpointForwardingTemplateBySubnet buildValue(final IpPrefix ipPrefix) {
+        return new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(ipPrefix)
+                .build();
+    }
+
+    @Test
+    public void testFind() throws Exception {
+        final EndpointForwardingTemplateBySubnet value1 = buildValue(IP_PREFIX_1);
+        final EndpointForwardingTemplateBySubnet value2 = buildValue(IP_PREFIX_2);
+        dao.update(IP_PREFIX_1, value1);
+        dao.update(IP_PREFIX_2, value2);
+        Assert.assertFalse(dao.isEmpty());
+
+        Assert.assertTrue(dao.find(IP_PREFIX_1).isPresent());
+        Assert.assertEquals(value1, dao.find(IP_PREFIX_1).get());
+        Assert.assertTrue(dao.find(IP_PREFIX_2).isPresent());
+        Assert.assertEquals(value2, dao.find(IP_PREFIX_2).get());
+
+        final IpPrefix key = buildIpPrefix("1.2.3.1/32");
+        Assert.assertTrue(dao.find(key).isPresent());
+        Assert.assertEquals(value1, dao.find(key).get());
+    }
+
+    private static IpPrefix buildIpPrefix(final String ipv4PrefixValue) {
+        return new IpPrefix(new Ipv4Prefix(ipv4PrefixValue));
+    }
+
+    @Test
+    public void testInvalidateCache() throws Exception {
+        dao.update(IP_PREFIX_1, buildValue(IP_PREFIX_1));
+        dao.update(IP_PREFIX_2, buildValue(IP_PREFIX_2));
+
+        Assert.assertEquals(2, Iterables.size(dao.values()));
+        dao.invalidateCache();
+        Assert.assertTrue(dao.isEmpty());
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/dao/SimpleCachedDaoImplTest.java
new file mode 100644 (file)
index 0000000..c66d366
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Test for {@link SimpleCachedDaoImpl}.
+ */
+public class SimpleCachedDaoImplTest {
+
+    private static final String KEY_1 = "dummyKey1";
+    private static final String KEY_2 = "dummyKey2";
+    private static final DummyDataObject DUMMY_DATA_1 = new DummyDataObject("dummyData1");
+    private static final DummyDataObject DUMMY_DATA_2 = new DummyDataObject("dummyData2");
+
+    private SimpleCachedDaoImpl<String, DummyDataObject> dao;
+
+    @Before
+    public void setUp() throws Exception {
+        dao = new SimpleCachedDaoImpl<>();
+        Assert.assertFalse(dao.find(KEY_1).isPresent());
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        dao.update(KEY_1, DUMMY_DATA_1);
+        final Optional<DummyDataObject> dataOpt = dao.find(KEY_1);
+        Assert.assertTrue(dataOpt.isPresent());
+        Assert.assertEquals(DUMMY_DATA_1.getDummyData(), dataOpt.get().getDummyData());
+    }
+
+    @Test
+    public void testInvalidateCache() throws Exception {
+        dao.update(KEY_1, DUMMY_DATA_1);
+        Assert.assertTrue(dao.find(KEY_1).isPresent());
+        dao.invalidateCache();
+        Assert.assertFalse(dao.find(KEY_1).isPresent());
+    }
+
+    @Test
+    public void testIsEmpty() throws Exception {
+        Assert.assertTrue(dao.isEmpty());
+        dao.update(KEY_1, DUMMY_DATA_1);
+        Assert.assertFalse(dao.isEmpty());
+    }
+
+    @Test
+    public void testValues() throws Exception {
+        Assert.assertEquals(0, Iterables.size(dao.values()));
+        dao.update(KEY_1, DUMMY_DATA_1);
+        dao.update(KEY_1, DUMMY_DATA_2);
+        Assert.assertEquals(1, Iterables.size(dao.values()));
+
+        dao.update(KEY_2, DUMMY_DATA_2);
+        Assert.assertEquals(2, Iterables.size(dao.values()));
+    }
+
+    private static final class DummyDataObject implements DataObject {
+        private final String dummyData;
+
+        public DummyDataObject(final String dummyData) {
+            this.dummyData = dummyData;
+        }
+
+        public String getDummyData() {
+            return dummyData;
+        }
+
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return getClass();
+        }
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPForwardingTemplateListenerImplTest.java
new file mode 100644 (file)
index 0000000..7dd05f3
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Test for {@link EPForwardingTemplateListenerImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EPForwardingTemplateListenerImplTest {
+
+    private static final IpPrefix IP_PREFIX_TMPL = buildIpPrefix("1.2.3.0/24");
+    private static final EndpointForwardingTemplateBySubnetKey EP_FW_TEMPLATE_KEY =
+            new EndpointForwardingTemplateBySubnetKey(IP_PREFIX_TMPL);
+    private static final KeyedInstanceIdentifier<EndpointForwardingTemplateBySubnet, EndpointForwardingTemplateBySubnetKey> EP_FW_TEMPLATE_PATH =
+            EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH
+                    .child(EndpointForwardingTemplateBySubnet.class, EP_FW_TEMPLATE_KEY);
+    private static final DataTreeIdentifier<EndpointForwardingTemplateBySubnet> TEMPLATE_TREE_PATH =
+            new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, EP_FW_TEMPLATE_PATH);
+    private final EndpointForwardingTemplateBySubnet EP_FW_TEMPLATE_VALUE;
+
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SxpMapperReactor sxpMapper;
+    @Mock
+    private SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> simpleCachedDao;
+    @Mock
+    private DSAsyncDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDao;
+    @Mock
+    private ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    @Mock
+    private DataTreeModification<EndpointForwardingTemplateBySubnet> dataTreeModification;
+    @Mock
+    private DataObjectModification<EndpointForwardingTemplateBySubnet> dataObjectModification;
+
+    private EPForwardingTemplateListenerImpl listener;
+
+    public EPForwardingTemplateListenerImplTest() {
+        EP_FW_TEMPLATE_VALUE = new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(IP_PREFIX_TMPL)
+                .build();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.<DataTreeIdentifier>any(),
+                Matchers.<DataTreeChangeListener>any())).thenReturn(listenerRegistration);
+        listener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBBindingDao);
+    }
+
+    @Test
+    public void testOnDataTreeChanged() throws Exception {
+        Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification);
+        Mockito.when(dataTreeModification.getRootPath()).thenReturn(TEMPLATE_TREE_PATH);
+        Mockito.when(dataObjectModification.getDataAfter()).thenReturn(EP_FW_TEMPLATE_VALUE);
+
+        final Sgt sgt = new Sgt(1);
+        final IpPrefix ipPrefix = buildIpPrefix("1.2.3.4/32");
+        final MasterDatabaseBinding prefixGroup = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(sgt)
+                .setIpPrefix(ipPrefix)
+                .build();
+        Mockito.when(masterDBBindingDao.read(Matchers.<IpPrefix>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(prefixGroup)));
+
+        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+        final InOrder inOrder = Mockito.inOrder(masterDBBindingDao, simpleCachedDao, sxpMapper);
+        inOrder.verify(simpleCachedDao).update(IP_PREFIX_TMPL, EP_FW_TEMPLATE_VALUE);
+        inOrder.verify(masterDBBindingDao).read(IP_PREFIX_TMPL);
+        inOrder.verify(sxpMapper).processForwardingAndSxpMasterDB(EP_FW_TEMPLATE_VALUE, prefixGroup);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    private static IpPrefix buildIpPrefix(final String ipv4PrefixValue) {
+        return new IpPrefix(new Ipv4Prefix(ipv4PrefixValue));
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        Mockito.verify(listenerRegistration, Mockito.never()).close();
+        listener.close();
+        Mockito.verify(listenerRegistration).close();
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/EPPolicyTemplateListenerImplTest.java
new file mode 100644 (file)
index 0000000..81fe8d0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Test for {@link EPPolicyTemplateListenerImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EPPolicyTemplateListenerImplTest {
+
+    private static final Sgt SGT_1 = new Sgt(1);
+    private static final KeyedInstanceIdentifier<EndpointPolicyTemplateBySgt, EndpointPolicyTemplateBySgtKey> EP_PL_TEMPLATE_PATH =
+            EPTemplateListener.SXP_MAPPER_TEMPLATE_PARENT_PATH
+                    .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(SGT_1));
+    private static final DataTreeIdentifier<EndpointPolicyTemplateBySgt> TEMPLATE_TREE_PATH =
+            new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, EP_PL_TEMPLATE_PATH);
+    private final EndpointPolicyTemplateBySgt EP_PL_TEMPLATE_VALUE;
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SxpMapperReactor sxpMapper;
+    @Mock
+    private SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> simpleCachedDao;
+    @Mock
+    private ReadableByKey<Sgt, MasterDatabaseBinding> masterDBDao;
+    @Mock
+    private ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    @Mock
+    private DataTreeModification<EndpointPolicyTemplateBySgt> dataTreeModification;
+    @Mock
+    private DataObjectModification<EndpointPolicyTemplateBySgt> dataObjectModification;
+
+    private EPPolicyTemplateListenerImpl listener;
+
+    public EPPolicyTemplateListenerImplTest() {
+        EP_PL_TEMPLATE_VALUE = new EndpointPolicyTemplateBySgtBuilder()
+                .setSgt(SGT_1)
+                .build();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.<DataTreeIdentifier>any(),
+                Matchers.<DataTreeChangeListener>any())).thenReturn(listenerRegistration);
+        listener = new EPPolicyTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBDao);
+    }
+
+    @Test
+    public void testOnDataTreeChanged() throws Exception {
+        Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification);
+        Mockito.when(dataTreeModification.getRootPath()).thenReturn(TEMPLATE_TREE_PATH);
+        Mockito.when(dataObjectModification.getDataAfter()).thenReturn(EP_PL_TEMPLATE_VALUE);
+
+        final MasterDatabaseBinding masterDBBinding = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(SGT_1)
+                .build();
+        Mockito.when(masterDBDao.readBy(Matchers.<Sgt>any())).thenReturn(
+                Futures.immediateFuture(Lists.newArrayList(masterDBBinding)));
+
+        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+        final InOrder inOrder = Mockito.inOrder(masterDBDao, simpleCachedDao, sxpMapper);
+        inOrder.verify(simpleCachedDao).update(SGT_1, EP_PL_TEMPLATE_VALUE);
+        inOrder.verify(masterDBDao).readBy(SGT_1);
+        inOrder.verify(sxpMapper).processPolicyAndSxpMasterDB(EP_PL_TEMPLATE_VALUE, masterDBBinding);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        Mockito.verify(listenerRegistration, Mockito.never()).close();
+        listener.close();
+        Mockito.verify(listenerRegistration).close();
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImplTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/listen/MasterDatabaseBindingListenerImplTest.java
new file mode 100644 (file)
index 0000000..fb77dd7
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.listen;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Test for {@link MasterDatabaseBindingListenerImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class MasterDatabaseBindingListenerImplTest {
+
+    private static final Sgt SGT_1 = new Sgt(1);
+    private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+    private static final KeyedInstanceIdentifier<MasterDatabaseBinding, MasterDatabaseBindingKey> MASTER_DB_PATH =
+            MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH
+                    .child(Node.class, new NodeKey(new NodeId("utNodeId")))
+                    .augmentation(SxpNodeIdentity.class)
+                    .child(MasterDatabase.class)
+                    .child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(IP_PREFIX));
+    private static final DataTreeIdentifier<MasterDatabaseBinding> MASTER_DB_BINDING_TREE_PATH =
+            new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, MASTER_DB_PATH);
+    private final MasterDatabaseBinding MASTER_DB_BINDING_VALUE;
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SxpMapperReactor sxpMapper;
+    @Mock
+    private DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+    @Mock
+    private DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
+    @Mock
+    private SimpleCachedDao<IpPrefix, MasterDatabaseBinding> cachedDao;
+    @Mock
+    private ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    @Mock
+    private DataTreeModification<MasterDatabaseBinding> dataTreeModification;
+    @Mock
+    private DataObjectModification<MasterDatabaseBinding> dataObjectModification;
+
+    private MasterDatabaseBindingListenerImpl listener;
+
+    public MasterDatabaseBindingListenerImplTest() {
+        MASTER_DB_BINDING_VALUE = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(SGT_1)
+                .setIpPrefix(IP_PREFIX)
+                .build();
+    }
+
+
+    @Before
+    public void setUp() throws Exception {
+        Mockito.when(dataBroker.registerDataTreeChangeListener(Matchers.<DataTreeIdentifier>any(),
+                Matchers.<DataTreeChangeListener>any())).thenReturn(listenerRegistration);
+        listener = new MasterDatabaseBindingListenerImpl(dataBroker, sxpMapper, cachedDao, epPolicyTemplateDao,
+                epForwardingTemplateDao);
+    }
+
+    @Test
+    public void testOnDataTreeChanged() throws Exception {
+        Mockito.when(dataTreeModification.getRootNode()).thenReturn(dataObjectModification);
+        Mockito.when(dataTreeModification.getRootPath()).thenReturn(MASTER_DB_BINDING_TREE_PATH);
+        Mockito.when(dataObjectModification.getDataAfter()).thenReturn(MASTER_DB_BINDING_VALUE);
+
+        // prepare epPolicy template
+        final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder()
+                .setSgt(SGT_1)
+                .build();
+        Mockito.when(epPolicyTemplateDao.read(Matchers.<Sgt>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(epPolicyTemplate)));
+
+        // prepare epForwarding template
+        final IpPrefix ipPrefixSubnet = new IpPrefix(new Ipv4Prefix("1.2.3.0/24"));
+        final EndpointForwardingTemplateBySubnet epForwardingTemplate = new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(ipPrefixSubnet)
+                .build();
+        Mockito.when(epForwardingTemplateDao.read(Matchers.<IpPrefix>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(epForwardingTemplate)));
+
+        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+        final InOrder inOrder = Mockito.inOrder(cachedDao, epPolicyTemplateDao, epForwardingTemplateDao, sxpMapper);
+        inOrder.verify(cachedDao).update(IP_PREFIX, MASTER_DB_BINDING_VALUE);
+        inOrder.verify(epPolicyTemplateDao).read(SGT_1);
+        inOrder.verify(sxpMapper).processPolicyAndSxpMasterDB(epPolicyTemplate, MASTER_DB_BINDING_VALUE);
+        inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX);
+        inOrder.verify(sxpMapper).processForwardingAndSxpMasterDB(epForwardingTemplate, MASTER_DB_BINDING_VALUE);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        Mockito.verify(listenerRegistration, Mockito.never()).close();
+        listener.close();
+        Mockito.verify(listenerRegistration).close();
+    }
+}
\ No newline at end of file
diff --git a/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtilTest.java b/sxp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/sxp/mapper/impl/util/ForwardingTemplateUtilTest.java
new file mode 100644 (file)
index 0000000..8a67e2b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+
+/**
+ * Test for {@link ForwardingTemplateUtil}.
+ */
+public class ForwardingTemplateUtilTest {
+
+    public static final IpPrefix IP_PREFIX_24 = new IpPrefix(new Ipv4Prefix("1.2.3.0/24"));
+    public static final IpPrefix IP_PREFIX_32 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+
+    @Test
+    public void testIsPlain() throws Exception {
+        Assert.assertFalse(ForwardingTemplateUtil.isPlain(IP_PREFIX_24));
+        Assert.assertTrue(ForwardingTemplateUtil.isPlain(IP_PREFIX_32));
+    }
+
+    @Test
+    public void testBuildSubnetInfoKey() throws Exception {
+        checkSubnetInfoBuilder(IP_PREFIX_24, "1.2.3.1", "1.2.3.254", 254);
+        checkSubnetInfoBuilder(IP_PREFIX_32, "0.0.0.0", "0.0.0.0", 0);
+    }
+
+    private void checkSubnetInfoBuilder(final IpPrefix ipPrefix, final String expectedLow, final String expectedHigh, final int expectedCount) {
+        final SubnetInfoKeyDecorator subnetInfoKey = ForwardingTemplateUtil.buildSubnetInfoKey(ipPrefix);
+        final SubnetUtils.SubnetInfo subnetInfo = subnetInfoKey.getDelegate();
+        Assert.assertEquals(expectedLow, subnetInfo.getLowAddress());
+        Assert.assertEquals(expectedHigh, subnetInfo.getHighAddress());
+        Assert.assertEquals(expectedCount, subnetInfo.getAddressCount());
+        Assert.assertEquals(ipPrefix.getIpv4Prefix().getValue(), subnetInfo.getCidrSignature());
+    }
+}
\ No newline at end of file