BUG-6650: ep-sgt/ip, propose initial sxp-ep-provider 51/42251/2
authorMichal Rehak <mirehak@cisco.com>
Thu, 21 Jul 2016 16:38:01 +0000 (18:38 +0200)
committerMichal Rehak <mirehak@cisco.com>
Mon, 3 Oct 2016 13:31:00 +0000 (15:31 +0200)
Change-Id: I639435ab23048cf318f4b760a5c1b92ae2249a97
Signed-off-by: Michal Rehak <mirehak@cisco.com>
(cherry picked from commit e97dcf9add5c5738035b28d970a7bb937be5f8c1)

49 files changed:
artifacts/pom.xml
pom.xml
sxp-integration/pom.xml [new file with mode: 0644]
sxp-integration/sxp-ep-provider/pom.xml [new file with mode: 0755]
sxp-integration/sxp-ep-provider/src/main/config/default-config.xml [new file with mode: 0755]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java [new file with mode: 0644]
sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml [new file with mode: 0644]

index 9cabf70958bc91c2565702f34acf332c52a1eaf6..3e66bcd5b5fcfb7ad17a6164fd38640946d3788e 100755 (executable)
         <artifactId>groupbasedpolicy-ise-adapter</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.groupbasedpolicy</groupId>
+        <artifactId>sxp-ep-provider</artifactId>
+        <version>${project.version}</version>
+      </dependency>
 
       <!-- GBP configuration -->
       <dependency>
diff --git a/pom.xml b/pom.xml
index 83080309e7251bd11c0aabcf6c73b3da9fce1847..4966133f22a1cc81f7dfba32257fe782b6c82f93 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
     <module>features</module>
     <module>sxp-mapper</module>
     <module>groupbasedpolicy-ise-adapter</module>
+    <module>sxp-integration</module>
   </modules>
 
   <build>
diff --git a/sxp-integration/pom.xml b/sxp-integration/pom.xml
new file mode 100644 (file)
index 0000000..a3180a6
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-parent</artifactId>
+        <version>0.6.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.groupbasedpolicy</groupId>
+    <artifactId>sxp-integration</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <sxp.version>1.4.0-SNAPSHOT</sxp.version>
+    </properties>
+
+    <modules>
+        <module>sxp-ep-provider</module>
+        <!--<module>ep-sgt-mapper</module>-->
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.groupbasedpolicy</groupId>
+                <artifactId>groupbasedpolicy-artifacts</artifactId>
+                <version>${project.version}</version>
+                <scope>import</scope>
+                <type>pom</type>
+            </dependency>
+
+            <!-- sxp -->
+            <dependency>
+                <groupId>org.opendaylight.sxp</groupId>
+                <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>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.groupbasedpolicy</groupId>
+            <artifactId>groupbasedpolicy</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/sxp-integration/sxp-ep-provider/pom.xml b/sxp-integration/sxp-ep-provider/pom.xml
new file mode 100755 (executable)
index 0000000..9e04c8c
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.groupbasedpolicy</groupId>
+        <artifactId>sxp-integration</artifactId>
+        <version>0.5.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>sxp-ep-provider</artifactId>
+    <packaging>bundle</packaging>
+    <name>sxp-integration_sxp-ep-provider</name>
+
+    <dependencies>
+        <!-- model dependencies -->
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>ietf-inet-types-2013-07-15</artifactId>
+
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>yang-ext</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.groupbasedpolicy</groupId>
+            <artifactId>l2-l3-domain-extension</artifactId>
+        </dependency>
+
+        <!-- sxp deps -->
+        <dependency>
+            <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>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <!-- project build -->
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sxp-integration/sxp-ep-provider/src/main/config/default-config.xml b/sxp-integration/sxp-ep-provider/src/main/config/default-config.xml
new file mode 100755 (executable)
index 0000000..0f2d59b
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2015 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
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:sxp-mapper="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-mapper">
+                        sxp-mapper:sxp-mapper-impl
+                    </type>
+                    <name>sxp-mapper</name>
+
+                    <data-broker>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                        <name>binding-data-broker</name>
+                    </data-broker>
+                    <rpc-registry>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+                        <name>binding-rpc-broker</name>
+                    </rpc-registry>
+                    <domain-specific-registry>
+                        <type xmlns:gbp="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy">
+                            gbp:domain-specific-registry
+                        </type>
+                        <name>domain-specific-registry</name>
+                    </domain-specific-registry>
+                </module>
+            </modules>
+        </data>
+
+    </configuration>
+
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-mapper?module=sxp-mapper-cfg&amp;revision=2016-03-02</capability>
+    </required-capabilities>
+
+</snapshot>
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModule.java
new file mode 100644 (file)
index 0000000..56458db
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider;
+
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpEpProviderProviderImpl;
+
+/**
+* sxp-ep-provider impl module
+*/
+public class SxpEpProviderProviderModule extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.AbstractSxpEpProviderProviderModule {
+    public SxpEpProviderProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public SxpEpProviderProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.SxpEpProviderProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new SxpEpProviderProviderImpl(getDataBrokerDependency(), getRpcRegistryDependency(),
+                getDomainSpecificRegistryDependency());
+    }
+
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/sxp_integration/sxp_ep_provider/SxpEpProviderProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..7e16cc4
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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
+ */
+
+/*
+* Generated file
+*
+* Generated from: yang module name: sxp-ep-provider-cfg yang module local name: sxp-ep-provider-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jul 21 17:55:05 CEST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider;
+public class SxpEpProviderProviderModuleFactory extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.sxp_integration.sxp_ep_provider.AbstractSxpEpProviderProviderModuleFactory {
+
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/DSAsyncDao.java
new file mode 100644 (file)
index 0000000..c97a134
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.ep.provider.impl;
+
+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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/EPTemplateListener.java
new file mode 100644 (file)
index 0000000..c6183f0
--- /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.ep.provider.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper;
+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 ClusteredDataTreeChangeListener<T>, AutoCloseable {
+
+    InstanceIdentifier<SxpEpMapper> SXP_MAPPER_TEMPLATE_PARENT_PATH = InstanceIdentifier.create(SxpEpMapper.class);
+
+    //NOBODY
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/IpPrefixEqualCommand.java
new file mode 100644 (file)
index 0000000..472a182
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.ep.provider.impl;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+
+/**
+ * Purpose: provide different strategies for {@link IpPrefix} comparison
+ */
+public interface IpPrefixEqualCommand {
+
+    boolean isEqualTo(IpPrefix value);
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/MasterDatabaseBindingListener.java
new file mode 100644 (file)
index 0000000..b278833
--- /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.ep.provider.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+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 ClusteredDataTreeChangeListener<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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableAsyncByKey.java
new file mode 100644 (file)
index 0000000..6ee9435
--- /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.ep.provider.impl;
+
+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 ReadableAsyncByKey<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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/ReadableByKey.java
new file mode 100644 (file)
index 0000000..5357544
--- /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.ep.provider.impl;
+
+import java.util.Collection;
+import javax.annotation.Nonnull;
+
+/**
+ * Purpose: simple 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
+     */
+    Collection<V> readBy(@Nonnull X specialKey);
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleCachedDao.java
new file mode 100644 (file)
index 0000000..913274b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.ep.provider.impl;
+
+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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SimpleDao.java
new file mode 100644 (file)
index 0000000..1196930
--- /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.ep.provider.impl;
+
+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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImpl.java
new file mode 100644 (file)
index 0000000..8fd1f47
--- /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.ep.provider.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Map.Entry;
+import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.ContainmentEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public class SxpEndpointAugmentorImpl implements EndpointAugmentor {
+
+    private final ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+    private final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory;
+
+    public SxpEndpointAugmentorImpl(final ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyTemplateDao,
+                                   final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory) {
+        this.epPolicyTemplateKeyFactory = Preconditions.checkNotNull(epPolicyTemplateKeyFactory, "epPolicyTemplateKeyFactory can not be null");
+        this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao, "epPolicyTemplateDao can not be null");
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<AddressEndpoint>>, Augmentation<AddressEndpoint>> buildAddressEndpointAugmentation(
+            AddressEndpointReg input) {
+        return null;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<ContainmentEndpoint>>, Augmentation<ContainmentEndpoint>> buildContainmentEndpointAugmentation(
+            ContainmentEndpointReg input) {
+        return null;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> buildAddressEndpointWithLocationAugmentation(
+            AddressEndpoint input) {
+        final EpPolicyTemplateValueKey templateValueKey = epPolicyTemplateKeyFactory.createKey(
+                input.getTenant(), input.getEndpointGroup(), input.getCondition());
+
+        final Collection<EndpointPolicyTemplateBySgt> epPolicyTemplates = epPolicyTemplateDao.readBy(templateValueKey);
+        final Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>> entry;
+
+        if (epPolicyTemplates.isEmpty()) {
+            entry = null;
+        } else {
+            //TODO: cover case when multiple templates found
+//            final Augmentation<AddressEndpointWithLocation> addressEndpointWithLocationAug =
+//                    new AddressEndpointWithLocationAugBuilder()
+//                            .setSgt(Iterables.getFirst(epPolicyTemplates, null).getSgt())
+//                            .build();
+//            entry = new AbstractMap.SimpleEntry<>(AddressEndpointWithLocationAug.class, addressEndpointWithLocationAug);
+        }
+
+        return null; //entry;
+    }
+
+    @Override
+    public Entry<Class<? extends Augmentation<ContainmentEndpointWithLocation>>, Augmentation<ContainmentEndpointWithLocation>> buildContainmentEndpointWithLocationAugmentation(
+            ContainmentEndpoint input) {
+        return null;
+    }
+
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java
new file mode 100644 (file)
index 0000000..8e3896f
--- /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.ep.provider.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.api.DomainSpecificRegistry;
+import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EPForwardingTemplateDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EPPolicyTemplateDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.MasterDatabaseBindingDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.SimpleCachedDaoEPForwardingTemplateImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.SimpleCachedDaoImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.EPForwardingTemplateListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.EPPolicyTemplateListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.listen.MasterDatabaseBindingListenerImpl;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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 SxpEpProviderProviderImpl implements AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SxpEpProviderProviderImpl.class);
+
+    private final MasterDatabaseBindingListenerImpl sxpDatabaseListener;
+    private final SxpMapperReactor sxpMapperReactor;
+    private final EPTemplateListener epPolicyTemplateListener;
+    private final EPTemplateListener epForwardingTemplateListener;
+    private final DomainSpecificRegistry domainSpecificRegistry;
+    private final EndpointAugmentor sxpEndpointAugmentor;
+
+    public SxpEpProviderProviderImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistryDependency,
+                                     final DomainSpecificRegistry domainSpecificRegistry) {
+        LOG.info("starting SxmMapper ..");
+        this.domainSpecificRegistry = domainSpecificRegistry;
+
+        final BaseEndpointService endpointService = rpcRegistryDependency.getRpcService(BaseEndpointService.class);
+        sxpMapperReactor = new SxpMapperReactorImpl(endpointService, dataBroker);
+
+        final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao = new SimpleCachedDaoImpl<>();
+        final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateCachedDao =
+                new SimpleCachedDaoEPForwardingTemplateImpl();
+        final SimpleCachedDao<IpPrefix, MasterDatabaseBinding> masterDBBindingCachedDao = new SimpleCachedDaoImpl<>();
+
+        final EpPolicyTemplateValueKeyFactory epPolicyTemplateKeyFactory = new EpPolicyTemplateValueKeyFactory(
+                EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+        final EPPolicyTemplateDaoImpl epPolicyTemplateDao = new EPPolicyTemplateDaoImpl(dataBroker, epPolicyTemplateCachedDao, epPolicyTemplateKeyFactory);
+        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, epForwardingTemplateDao);
+        epForwardingTemplateListener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapperReactor, epForwardingTemplateCachedDao,
+                masterDBBindingDao, epPolicyTemplateDao);
+        sxpEndpointAugmentor = new SxpEndpointAugmentorImpl(epPolicyTemplateDao, epPolicyTemplateKeyFactory);
+        domainSpecificRegistry.getEndpointAugmentorRegistry().register(sxpEndpointAugmentor);
+        LOG.info("started SxmMapper");
+    }
+
+    @Override
+    public void close() throws Exception {
+        sxpDatabaseListener.close();
+        epPolicyTemplateListener.close();
+        epForwardingTemplateListener.close();
+        domainSpecificRegistry.getEndpointAugmentorRegistry().unregister(sxpEndpointAugmentor);
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactor.java
new file mode 100644 (file)
index 0000000..8e5c46e
--- /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.ep.provider.impl;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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 policy template
+     * @param epForwardingTemplate forwarding template
+     * @param masterDatabaseBinding sxpMasterDB item
+     */
+    ListenableFuture<RpcResult<Void>> processTemplatesAndSxpMasterDB(EndpointPolicyTemplateBySgt epPolicyTemplate,
+                                                                     EndpointForwardingTemplateBySubnet epForwardingTemplate,
+                                                                     MasterDatabaseBinding masterDatabaseBinding);
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImpl.java
new file mode 100644 (file)
index 0000000..be94916
--- /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.ep.provider.impl;
+
+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.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collections;
+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.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: exclusively processes sxp master database changes and EGP templates changes
+ */
+public class SxpMapperReactorImpl implements SxpMapperReactor {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SxpMapperReactorImpl.class);
+
+    private final BaseEndpointService l3EndpointService;
+    private final DataBroker dataBroker;
+
+    public SxpMapperReactorImpl(final BaseEndpointService l3EndpointService, final DataBroker dataBroker) {
+        this.l3EndpointService = Preconditions.checkNotNull(l3EndpointService, "l3Endpoint service missing");
+        this.dataBroker = Preconditions.checkNotNull(dataBroker, "dataBroker missing");
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<Void>> processTemplatesAndSxpMasterDB(
+            final EndpointPolicyTemplateBySgt epPolicyTemplate,
+            final EndpointForwardingTemplateBySubnet epForwardingTemplate,
+            final MasterDatabaseBinding masterDBBinding) {
+        LOG.debug("processing ep-templates + sxpMasterDB entry: {} - {}",
+                masterDBBinding.getSecurityGroupTag(), masterDBBinding.getIpPrefix());
+        // apply sxpMasterDB to policy template
+        final Ipv4Prefix address = new Ipv4Prefix(epForwardingTemplate.getIpPrefix().getIpv4Prefix().getValue());
+        final NetworkContainment networkContainment = new NetworkContainmentBuilder()
+            .setContainment(new NetworkDomainContainmentBuilder()
+            .setNetworkDomainType(epForwardingTemplate.getNetworkContainment().getNetworkDomainType())
+            .setNetworkDomainId(epForwardingTemplate.getNetworkContainment().getNetworkDomainId())
+            .build())
+                    .build();
+        final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(
+                Collections.singletonList(new AddressEndpointRegBuilder().setAddressType(IpPrefixType.class)
+                    .setAddress(address.getValue())
+                    .setContextType(L3Context.class)
+                    .setContextId(epForwardingTemplate.getL3Context())
+                    .setNetworkContainment(networkContainment)
+                    .setCondition(epPolicyTemplate.getConditions())
+                    .setTenant(epPolicyTemplate.getTenant())
+                    .setEndpointGroup(epPolicyTemplate.getEndpointGroups())
+                    .build()))
+                .build();
+                epForwardingTemplate.getL3Context();
+
+        return chainL3EPServiceIfEpAbsent(epInput);
+    }
+
+    private CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> findExistingEndPoint(final ContextId containment,
+                                                                                          final String address) {
+        KeyedInstanceIdentifier<AddressEndpoint, AddressEndpointKey> addressEndpointPath =
+                InstanceIdentifier.create(Endpoints.class).child(AddressEndpoints.class).child(AddressEndpoint.class,
+                        new AddressEndpointKey(address, IpPrefixType.class, containment, L3Context.class));
+        final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        final CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> read = rTx.read(
+                LogicalDatastoreType.OPERATIONAL, addressEndpointPath);
+        Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
+        return read;
+    }
+
+    private ListenableFuture<RpcResult<Void>> chainL3EPServiceIfEpAbsent(final RegisterEndpointInput epInput) {
+        AddressEndpointReg addressEndpoint = epInput.getAddressEndpointReg().get(0);
+        CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> existingEndpointFuture =
+                findExistingEndPoint(addressEndpoint.getContextId(), addressEndpoint.getAddress());
+
+        return Futures.transform(existingEndpointFuture, new AsyncFunction<Optional<AddressEndpoint>, RpcResult<Void>>() {
+            @Override
+            public ListenableFuture<RpcResult<Void>> apply(final Optional<AddressEndpoint> input) throws Exception {
+                final ListenableFuture<RpcResult<Void>> nextResult;
+                if (input == null || !input.isPresent() || !isSameEpg(epInput, input.get())) {
+                    // invoke service
+                    return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(epInput));
+                } else {
+                    final String existingL3EpMsg = String.format("address-endpoint for given key already exists: %s | %s",
+                            addressEndpoint.getContextId(), addressEndpoint.getAddress() );
+                    nextResult = Futures.immediateFailedFuture(new IllegalStateException(existingL3EpMsg));
+                }
+                return nextResult;
+            }
+        });
+    }
+
+    private boolean isSameEpg(RegisterEndpointInput epInput, AddressEndpoint input) {
+        if (epInput == null || epInput.getAddressEndpointReg() == null || epInput.getAddressEndpointReg().isEmpty()) {
+            return true;
+        }
+        final AddressEndpointReg epInputAddressEndpoint = epInput.getAddressEndpointReg().get(0);
+        if (epInputAddressEndpoint.getEndpointGroup() == null || epInputAddressEndpoint.getEndpointGroup().isEmpty()) {
+            return true;
+        }
+        if (input == null || input.getEndpointGroup() == null || input.getEndpointGroup().isEmpty()) {
+            return true;
+        }
+        final EndpointGroupId addressEndpointGroupId = epInputAddressEndpoint.getEndpointGroup().get(0);
+        final EndpointGroupId existingEndpointGroupId = input.getEndpointGroup().get(0);
+        return addressEndpointGroupId.equals(existingEndpointGroupId);
+    }
+
+}
+
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImpl.java
new file mode 100644 (file)
index 0000000..31458ed
--- /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.ep.provider.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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Purpose: general dao for EndPoint templates
+ */
+public class EPForwardingTemplateDaoImpl implements DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> {
+
+    private 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<SxpEpMapper>, ReadFailedException> read =
+                    rTx.read(LogicalDatastoreType.CONFIGURATION, buildReadPath(key));
+
+            Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
+
+            readResult = Futures.transform(read, new Function<Optional<SxpEpMapper>, Optional<EndpointForwardingTemplateBySubnet>>() {
+                @Nullable
+                @Override
+                public Optional<EndpointForwardingTemplateBySubnet> apply(@Nullable final Optional<SxpEpMapper> 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 lookup(cachedDao, key);
+                    } else {
+                        return Optional.absent();
+                    }
+                }
+            });
+        }
+        return readResult;
+    }
+
+    protected InstanceIdentifier<SxpEpMapper> 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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImpl.java
new file mode 100644 (file)
index 0000000..d53f138
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.ep.provider.impl.dao;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+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 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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableByKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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>,
+        ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> {
+
+    private static final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent());
+
+    private final DataBroker dataBroker;
+    private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao;
+    private final EpPolicyTemplateValueKeyFactory keyFactory;
+
+    public EPPolicyTemplateDaoImpl(final DataBroker dataBroker,
+                                   final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> cachedDao,
+                                   final EpPolicyTemplateValueKeyFactory keyFactory) {
+        this.dataBroker = dataBroker;
+        this.cachedDao = cachedDao;
+        this.keyFactory = keyFactory;
+    }
+
+    @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 if (!cachedDao.isEmpty()) {
+            return READ_FUTURE_ABSENT;
+        } 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, keyFactory.sortValueKeyLists(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);
+    }
+
+    @Override
+    public Collection<EndpointPolicyTemplateBySgt> readBy(@Nonnull final EpPolicyTemplateValueKey specialKey) {
+        final Predicate<EpPolicyTemplateValueKey> templateValuePredicate = Predicates.equalTo(specialKey);
+        final Collection<EndpointPolicyTemplateBySgt> foundTemplates = new ArrayList<>();
+
+        for (EndpointPolicyTemplateBySgt epPolicyTemplate : cachedDao.values()) {
+            final EpPolicyTemplateValueKey templateValueKey = keyFactory.createKeyWithDefaultOrdering(epPolicyTemplate);
+            if (templateValuePredicate.apply(templateValueKey)) {
+                foundTemplates.add(epPolicyTemplate);
+            }
+        }
+
+        return foundTemplates;
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKey.java
new file mode 100644 (file)
index 0000000..83ee793
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.ep.provider.impl.dao;
+
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+
+/**
+ * Purpose: composite key holcer for {@link EndpointPolicyTemplateBySgt}
+ */
+public class EpPolicyTemplateValueKey {
+
+    private final TenantId tenantId;
+    private final List<EndpointGroupId> epgId;
+    private final List<ConditionName> conditionName;
+
+    public EpPolicyTemplateValueKey(final TenantId tenantId, final List<EndpointGroupId> epgId, final List<ConditionName> conditionName) {
+        this.tenantId = tenantId;
+        this.epgId = epgId;
+        this.conditionName = conditionName;
+    }
+
+    public EpPolicyTemplateValueKey(AddressEndpointWithLocation endpoint) {
+        this(endpoint.getTenant(), endpoint.getEndpointGroup(), endpoint.getCondition());
+    }
+
+    public TenantId getTenantId() {
+        return tenantId;
+    }
+
+    public List<EndpointGroupId> getEpgId() {
+        return epgId;
+    }
+
+    public List<ConditionName> getConditionName() {
+        return conditionName;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        final EpPolicyTemplateValueKey that = (EpPolicyTemplateValueKey) o;
+
+        if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
+        if (epgId != null ? !epgId.equals(that.epgId) : that.epgId != null) return false;
+        return conditionName != null ? conditionName.equals(that.conditionName) : that.conditionName == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        return tenantId != null ? tenantId.hashCode() : 0;
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EpPolicyTemplateValueKeyFactory.java
new file mode 100644 (file)
index 0000000..58190d4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.ep.provider.impl.dao;
+
+import com.google.common.collect.Ordering;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+
+/**
+ * Purpose: create cache keys with ordered lists inside
+ */
+public class EpPolicyTemplateValueKeyFactory {
+    private final Ordering<EndpointGroupId> epgIdOrdering;
+    private final Ordering<ConditionName> conditionOrdering;
+
+    public EpPolicyTemplateValueKeyFactory(final Ordering<EndpointGroupId> epgIdOrdering,
+                                           final Ordering<ConditionName> conditionOrdering) {
+        this.epgIdOrdering = epgIdOrdering;
+        this.conditionOrdering = conditionOrdering;
+    }
+
+    public EndpointPolicyTemplateBySgt sortValueKeyLists(final EndpointPolicyTemplateBySgt template) {
+        if (template.getEndpointGroups() != null) {
+            Collections.sort(template.getEndpointGroups(), epgIdOrdering);
+        }
+        if (template.getConditions() != null) {
+            Collections.sort(template.getConditions(), conditionOrdering);
+        }
+        return template;
+    }
+
+    public EpPolicyTemplateValueKey createKeyWithDefaultOrdering(final EndpointPolicyTemplateBySgt newSource) {
+        return new EpPolicyTemplateValueKey(
+                newSource.getTenant(), newSource.getEndpointGroups(), newSource.getConditions());
+    }
+
+    public EpPolicyTemplateValueKey sortValueKeyLists(final EpPolicyTemplateValueKey existingKey) {
+        Collections.sort(existingKey.getEpgId(), epgIdOrdering);
+        if (existingKey.getConditionName() != null) {
+            Collections.sort(existingKey.getConditionName(), conditionOrdering);
+        }
+        return existingKey;
+    }
+
+    public EpPolicyTemplateValueKey createKey(final TenantId tenant, final List<EndpointGroupId> endpointGroup,
+                                              final List<ConditionName> condition) {
+        return sortValueKeyLists(new EpPolicyTemplateValueKey(tenant, endpointGroup, condition));
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImpl.java
new file mode 100644 (file)
index 0000000..ebf16d3
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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.ep.provider.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 java.util.stream.Collectors;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.MasterDatabaseFields;
+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.SxpDatabasesFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
+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>,
+        ReadableAsyncByKey<Sgt, MasterDatabaseBinding> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseBindingDaoImpl.class);
+    private static final ListenableFuture<Optional<MasterDatabaseBinding>> READ_FUTURE_ABSENT = Futures.immediateFuture(Optional.absent());
+
+    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 if (!cachedDao.isEmpty()) {
+            return READ_FUTURE_ABSENT;
+        } 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()) {
+                        java.util.Optional.ofNullable(node.getAugmentation(SxpNodeIdentity.class))
+                                .map(SxpNodeIdentity::getSxpDomains)
+                                .map(SxpDomains::getSxpDomain)
+                                .ifPresent((sxpDomain) -> {
+                                    final List<MasterDatabaseBinding> masterDBBindings = sxpDomain.stream()
+                                            .map(SxpDatabasesFields::getMasterDatabase)
+                                            .filter(masterDb -> masterDb != null)
+                                            .map(MasterDatabaseFields::getMasterDatabaseBinding)
+                                            .filter(binding -> binding != null)
+                                            .flatMap(Collection::stream)
+                                            .collect(Collectors.toList());
+
+                                    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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImpl.java
new file mode 100644 (file)
index 0000000..e04aa1a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.ep.provider.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.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SubnetInfoKeyDecorator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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 (EPTemplateUtil.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 = EPTemplateUtil.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 (EPTemplateUtil.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 = EPTemplateUtil.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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImpl.java
new file mode 100644 (file)
index 0000000..a6c1629
--- /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.ep.provider.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.ep.provider.impl.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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImpl.java
new file mode 100644 (file)
index 0000000..4b89303
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.ep.provider.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.apache.commons.lang3.tuple.Pair;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+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;
+    private final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+
+    public EPForwardingTemplateListenerImpl(final DataBroker dataBroker,
+                                            final SxpMapperReactor sxpMapperReactor,
+                                            final SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> templateCachedDao,
+                                            final DSAsyncDao<IpPrefix, MasterDatabaseBinding> masterDBBindingDao,
+                                            final DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao) {
+        this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
+        this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao);
+        this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao);
+        this.epPolicyTemplateDao = Preconditions.checkNotNull(epPolicyTemplateDao);
+        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();
+            processWithEPTemplates(epForwardingTemplate);
+        }
+    }
+
+    private void processWithEPTemplates(final EndpointForwardingTemplateBySubnet epForwardingTemplate) {
+        final ListenableFuture<Optional<MasterDatabaseBinding>> sxpMasterDbItemRead =
+                masterDBBindingDao.read(epForwardingTemplate.getIpPrefix());
+
+        // find all available epForwardingTemplates and pair those to sxpMasterDBBinding
+        final ListenableFuture<Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>> searchResult =
+                Futures.transform(sxpMasterDbItemRead, createReadAndPairTemplateToBindingFunction(epForwardingTemplate));
+
+        // invoke sxpMapperReactor.process for every valid combination of sxpMasterDBBinding, epPolicyTemplate, epForwardingTemplate
+        final ListenableFuture<RpcResult<Void>> rpcResult =
+                Futures.transform(searchResult, createProcessAllFunction(epForwardingTemplate));
+
+        Futures.addCallback(rpcResult, ANY_RPC_FUTURE_CALLBACK);
+    }
+
+    private AsyncFunction<Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>, RpcResult<Void>>
+    createProcessAllFunction(final EndpointForwardingTemplateBySubnet epForwardingTemplate) {
+        return new AsyncFunction<Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>, RpcResult<Void>>() {
+            @Override
+            public ListenableFuture<RpcResult<Void>>
+            apply(final Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>> input) throws Exception {
+                final ListenableFuture<RpcResult<Void>> result;
+                if (input == null || !input.isPresent()) {
+                    LOG.debug("no epPolicyTemplate available for ip-prefix: {}", epForwardingTemplate.getIpPrefix());
+                    result = Futures.immediateFuture(
+                            RpcResultBuilder.<Void>failed()
+                                    .withError(RpcError.ErrorType.APPLICATION,
+                                            "no epForwardingTemplate available for ip-prefix " + epForwardingTemplate.getIpPrefix())
+                                    .build());
+                } else {
+                    LOG.trace("processing epForwardingTemplate event for ip-prefix: {}", epForwardingTemplate.getIpPrefix());
+                    final Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt> pair = input.get();
+                    final MasterDatabaseBinding sxpMasterDBBinding = pair.getLeft();
+                    final EndpointPolicyTemplateBySgt epPolicyTemplate = pair.getRight();
+                    LOG.trace("processing epForwardingTemplate event with resolved sxpMasterDb entry and " +
+                                    "epPolicyTemplate for sgt/ip-prefix: {}/{}",
+                            sxpMasterDBBinding.getSecurityGroupTag(), sxpMasterDBBinding.getImplementedInterface());
+                    result = sxpMapperReactor.processTemplatesAndSxpMasterDB(epPolicyTemplate, epForwardingTemplate, sxpMasterDBBinding);
+                }
+
+                return result;
+            }
+        };
+    }
+
+    private AsyncFunction<Optional<MasterDatabaseBinding>, Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>>
+    createReadAndPairTemplateToBindingFunction(final EndpointForwardingTemplateBySubnet epFowardingTemplate) {
+        return new AsyncFunction<Optional<MasterDatabaseBinding>, Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>>() {
+            @Override
+            public ListenableFuture<Optional<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>>>
+            apply(final Optional<MasterDatabaseBinding> input) throws Exception {
+                final ListenableFuture<Pair<MasterDatabaseBinding, EndpointPolicyTemplateBySgt>> result;
+                if (input == null || !input.isPresent()) {
+                    LOG.debug("no sxpMasterDB entry available for ip-prefix: {}", epFowardingTemplate.getIpPrefix());
+                    result = Futures.immediateFuture(null);
+                } else {
+                    LOG.trace("processing sxpMasterDB entry for ip-prefix: {}", epFowardingTemplate.getIpPrefix());
+                    final MasterDatabaseBinding masterDBItem = input.get();
+                    final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> epPolicyTemplateRead =
+                            epPolicyTemplateDao.read(masterDBItem.getSecurityGroupTag());
+                    result = EPTemplateUtil.wrapToPair(masterDBItem, epPolicyTemplateRead);
+                }
+
+                return EPTemplateUtil.wrapToOptional(result);
+            }
+        };
+    }
+
+
+    @Override
+    public void close() throws Exception {
+        LOG.debug("closing listener registration to {}", templatePath);
+        listenerRegistration.close();
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImpl.java
new file mode 100644 (file)
index 0000000..a31d4ac
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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.ep.provider.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.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.apache.commons.lang3.tuple.Pair;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+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 ReadableAsyncByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao;
+    private final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
+
+    public EPPolicyTemplateListenerImpl(final DataBroker dataBroker,
+                                        final SxpMapperReactor sxpMapperReactor,
+                                        final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> templateCachedDao,
+                                        final ReadableAsyncByKey<Sgt, MasterDatabaseBinding> masterDBBindingDao,
+                                        final DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao) {
+        this.sxpMapperReactor = Preconditions.checkNotNull(sxpMapperReactor);
+        this.templateCachedDao = Preconditions.checkNotNull(templateCachedDao);
+        this.masterDBBindingDao = Preconditions.checkNotNull(masterDBBindingDao);
+        this.epForwardingTemplateDao = Preconditions.checkNotNull(epForwardingTemplateDao);
+        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();
+            processWithEPTemplates(epPolicyTemplate);
+        }
+    }
+
+    private void processWithEPTemplates(final EndpointPolicyTemplateBySgt epPolicyTemplate) {
+        final ListenableFuture<Collection<MasterDatabaseBinding>> sxpMasterDbItemsRead =
+                masterDBBindingDao.readBy(epPolicyTemplate.getSgt());
+
+        // find all available epForwardingTemplates and pair those to sxpMasterDBBinding
+        final ListenableFuture<List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>> epForwardingTemplatesRead =
+                Futures.transform(sxpMasterDbItemsRead, createReadAndPairTemplateToBindingFunction(epPolicyTemplate));
+
+        // invoke sxpMapperReactor.process for every valid combination of sxpMasterDBBinding, epPolicyTemplate, epForwardingTemplate
+        final ListenableFuture<List<RpcResult<Void>>> rpcResult =
+                Futures.transform(epForwardingTemplatesRead, createProcessAllFunction(epPolicyTemplate));
+
+        Futures.addCallback(rpcResult, RPC_RESULT_FUTURE_CALLBACK);
+    }
+
+    private AsyncFunction<List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>, List<RpcResult<Void>>>
+    createProcessAllFunction(final EndpointPolicyTemplateBySgt epPolicyTemplate) {
+        return new AsyncFunction<List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>, List<RpcResult<Void>>>() {
+            @Override
+            public ListenableFuture<List<RpcResult<Void>>>
+            apply(final List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>> input) throws Exception {
+                final ListenableFuture<List<RpcResult<Void>>> result;
+                if (input == null || input.isEmpty()) {
+                    LOG.debug("no epForwardingTemplate available for sgt: {}", epPolicyTemplate.getSgt());
+                    result = Futures.immediateFuture(Collections.singletonList(
+                            RpcResultBuilder.<Void>failed()
+                                    .withError(RpcError.ErrorType.APPLICATION,
+                                            "no epForwardingTemplate available for sgt " + epPolicyTemplate.getSgt())
+                                    .build()));
+                } else {
+                    LOG.trace("processing epPolicyTemplate event for sgt: {}", epPolicyTemplate.getSgt());
+                    List<ListenableFuture<RpcResult<Void>>> allResults = new ArrayList<>(input.size());
+                    for (Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet> pair : input) {
+                        final MasterDatabaseBinding sxpMasterDBBinding = pair.getLeft();
+                        final EndpointForwardingTemplateBySubnet epForwardingTemplate = pair.getRight();
+                        if (epForwardingTemplate != null) {
+                            LOG.trace("processing epPolicyTemplate event with resolved sxpMasterDb entry and " +
+                                            "epForwardingTemplate for sgt/ip-prefix: {}/{}",
+                                    sxpMasterDBBinding.getSecurityGroupTag(), sxpMasterDBBinding.getImplementedInterface());
+                            allResults.add(sxpMapperReactor.processTemplatesAndSxpMasterDB(
+                                    epPolicyTemplate, epForwardingTemplate, sxpMasterDBBinding));
+                        }
+                    }
+                    result = Futures.successfulAsList(allResults);
+                }
+
+                return result;
+            }
+};
+    }
+
+    private AsyncFunction<Collection<MasterDatabaseBinding>, List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>>
+    createReadAndPairTemplateToBindingFunction(final EndpointPolicyTemplateBySgt epPolicyTemplate) {
+        return new AsyncFunction<Collection<MasterDatabaseBinding>, List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>>() {
+            @Override
+            public ListenableFuture<List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>>
+            apply(final Collection<MasterDatabaseBinding> input) throws Exception {
+                final ListenableFuture<List<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>> result;
+                if (input == null || input.isEmpty()) {
+                    LOG.debug("no sxpMasterDB entry available for sgt: {}", epPolicyTemplate.getSgt());
+                    result = Futures.immediateFuture(Collections.emptyList());
+                } else {
+                    LOG.trace("processing sxpMasterDB entries for sgt: {}", epPolicyTemplate.getSgt());
+                    List<ListenableFuture<Pair<MasterDatabaseBinding, EndpointForwardingTemplateBySubnet>>> allResults =
+                            new ArrayList<>(input.size());
+                    for (MasterDatabaseBinding masterDBItem : input) {
+                        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> epForwardingTemplateRead =
+                                epForwardingTemplateDao.read(masterDBItem.getIpPrefix());
+                        allResults.add(EPTemplateUtil.wrapToPair(masterDBItem, epForwardingTemplateRead));
+                    }
+                    result = Futures.successfulAsList(allResults);
+                }
+
+                return result;
+            }
+        };
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.debug("closing listener registration to {}", templatePath);
+        listenerRegistration.close();
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImpl.java
new file mode 100644 (file)
index 0000000..9e65b3b
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.ep.provider.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.ClusteredDataTreeChangeListener;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.L3EPServiceUtil;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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.network.topology.topology.node.SxpDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
+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.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+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 ClusteredDataTreeChangeListener> 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);
+
+        //TODO: get exact sxp-node path from config (pointing to ise listener).. start listening later - when config appears
+        sxpDbPath = MasterDatabaseBindingListener.SXP_TOPOLOGY_PATH
+                .child(Node.class)
+                .augmentation(SxpNodeIdentity.class)
+                .child(SxpDomains.class)
+                .child(SxpDomain.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
+                LOG.debug("ip-sgt mapping was removed - NOOP: {}",
+                        change.getRootPath().getRootIdentifier().firstKeyOf(MasterDatabaseBinding.class));
+            } else {
+                final IpPrefix ipPrefixKey = sxpMasterDBItem.getIpPrefix();
+                SxpListenerUtil.updateCachedDao(masterDBBindingDaoCached, ipPrefixKey, change);
+                processWithEPTemplates(sxpMasterDBItem);
+            }
+        }
+    }
+
+    private void processWithEPTemplates(final MasterDatabaseBinding sxpMasterDBItem) {
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> epPolicyTemplateFuture =
+                epPolicyTemplateDao.read(sxpMasterDBItem.getSecurityGroupTag());
+
+        final ListenableFuture<Optional<EndpointForwardingTemplateBySubnet>> epForwardingTemplateFuture =
+                epForwardingTemplateDao.read(sxpMasterDBItem.getIpPrefix());
+
+        final ListenableFuture<EPTemplateUtil.OptionalMutablePair<EndpointPolicyTemplateBySgt, EndpointForwardingTemplateBySubnet>> compositeRead
+                = EPTemplateUtil.compositeRead(epPolicyTemplateFuture, epForwardingTemplateFuture);
+
+        final ListenableFuture<RpcResult<Void>> rpcResult = Futures.transform(compositeRead,
+                new AsyncFunction<EPTemplateUtil.OptionalMutablePair<EndpointPolicyTemplateBySgt, EndpointForwardingTemplateBySubnet>, RpcResult<Void>>() {
+                    @Override
+                    public ListenableFuture<RpcResult<Void>> apply(final EPTemplateUtil.OptionalMutablePair<EndpointPolicyTemplateBySgt, EndpointForwardingTemplateBySubnet> input) throws Exception {
+                        final ListenableFuture<RpcResult<Void>> result;
+                        if (input == null) {
+                            LOG.debug("no ep*Templates available for sgt/ip-prefix: {}/{}",
+                                    sxpMasterDBItem.getSecurityGroupTag(),
+                                    sxpMasterDBItem.getIpPrefix());
+                            result = RpcResultBuilder.<Void>failed()
+                                    .withError(RpcError.ErrorType.APPLICATION,
+                                            "no ep-templates available for" + sxpMasterDBItem)
+                                    .buildFuture();
+
+                        } else if (!input.getLeft().isPresent()) {
+                            LOG.debug("no epPolicyTemplate available for sgt: {}", sxpMasterDBItem.getSecurityGroupTag());
+                            result = RpcResultBuilder.<Void>failed()
+                                    .withError(RpcError.ErrorType.APPLICATION,
+                                            "no epPolicyTemplate available for " + sxpMasterDBItem)
+                                    .buildFuture();
+                        } else if (!input.getRight().isPresent()) {
+                            LOG.debug("no epForwardingTemplate available for ip-prefix: {}",
+                                    sxpMasterDBItem.getIpPrefix());
+                            result = RpcResultBuilder.<Void>failed()
+                                    .withError(RpcError.ErrorType.APPLICATION,
+                                            "no epForwardingTemplate available for " + sxpMasterDBItem)
+                                    .buildFuture();
+                        } else {
+                            LOG.trace("processing sxpMasterDB event and epPolicyTemplate for sgt/ip-prefix: {}/{}",
+                                    sxpMasterDBItem.getSecurityGroupTag(),
+                                    sxpMasterDBItem.getIpPrefix());
+                            result = sxpMapperReactor.processTemplatesAndSxpMasterDB(input.getLeft().get(),
+                                    input.getRight().get(), sxpMasterDBItem);
+                }
+                return result;
+            }
+        });
+
+        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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtil.java
new file mode 100644 (file)
index 0000000..f7ea755
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.ep.provider.impl.util;
+
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import com.google.common.collect.Ordering;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+
+/**
+ * Purpose: util methods for {@link EndpointForwardingTemplateBySubnet} and {@link EndpointPolicyTemplateBySgt}
+ */
+public final class EPTemplateUtil {
+
+    public static final String FULL_IPV4_MASK_SUFFIX = "/32";
+    private static final Comparable EMPTY_COMPARABLE = "";
+
+    private EPTemplateUtil() {
+        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());
+    }
+
+    public static <L, R> ListenableFuture<OptionalMutablePair<L, R>> compositeRead(
+            final ListenableFuture<Optional<L>> leftRead, final ListenableFuture<Optional<R>> rightRead) {
+
+        final OptionalMutablePair<L, R> compositeResult = new OptionalMutablePair<>();
+        final List<ListenableFuture<?>> results = new ArrayList<>(2);
+
+        results.add(Futures.transform(leftRead, new Function<Optional<L>, OptionalMutablePair<L, R>>() {
+            @Nullable
+            @Override
+            public OptionalMutablePair<L, R> apply(@Nullable final Optional<L> input) {
+                compositeResult.setLeft(input);
+                return compositeResult;
+            }
+        }));
+
+        results.add(Futures.transform(rightRead, new Function<Optional<R>, OptionalMutablePair<L, R>>() {
+            @Nullable
+            @Override
+            public OptionalMutablePair<L, R> apply(@Nullable final Optional<R> input) {
+                compositeResult.setRight(input);
+                return compositeResult;
+            }
+        }));
+
+        return Futures.transform(Futures.successfulAsList(results),
+                new Function<List<?>, OptionalMutablePair<L, R>>() {
+                    @Nullable
+                    @Override
+                    public OptionalMutablePair<L, R> apply(@Nullable final List<?> input) {
+                        return compositeResult;
+                    }
+                });
+    }
+
+    public static <K, V> ListenableFuture<Pair<K, V>> wrapToPair(
+            final K keyItem,
+            final ListenableFuture<Optional<V>> valueFromRead) {
+        return Futures.transform(valueFromRead, new Function<Optional<V>, Pair<K, V>>() {
+            @Nullable
+            @Override
+            public Pair<K, V> apply(@Nullable final Optional<V> input) {
+                return new MutablePair<>(keyItem, input.orNull());
+            }
+        });
+    }
+
+    public static <V> ListenableFuture<Optional<V>> wrapToOptional(final ListenableFuture<V> value) {
+        return Futures.transform(value, new Function<V, Optional<V>>() {
+            @Nullable
+            @Override
+            public Optional<V> apply(@Nullable final V input) {
+                return Optional.fromNullable(input);
+            }
+        });
+    }
+
+    public static Ordering<EndpointGroupId> createEndpointGroupIdOrdering() {
+        return Ordering.natural().onResultOf(new Function<EndpointGroupId, Comparable>() {
+            @Nullable
+            @Override
+            public Comparable apply(@Nullable final EndpointGroupId input) {
+                if (input == null) {
+                    return EMPTY_COMPARABLE;
+                }
+                return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+            }
+        });
+    }
+
+    public static Ordering<ConditionName> createConditionNameOrdering() {
+        return Ordering.natural().onResultOf(new Function<ConditionName, Comparable>() {
+            @Nullable
+            @Override
+            public Comparable apply(@Nullable final ConditionName input) {
+                if (input == null) {
+                    return EMPTY_COMPARABLE;
+                }
+                return MoreObjects.firstNonNull(input.getValue(), EMPTY_COMPARABLE);
+            }
+        });
+    }
+
+    public static class OptionalMutablePair<L, R> extends MutablePair<Optional<L>, Optional<R>> {
+        public OptionalMutablePair() {
+            super(Optional.absent(), Optional.absent());
+        }
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandDirectImpl.java
new file mode 100644 (file)
index 0000000..e5fe29a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.ep.provider.impl.util;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.IpPrefixEqualCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/IpPrefixEqualCommandSubnetImpl.java
new file mode 100644 (file)
index 0000000..673abe8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.ep.provider.impl.util;
+
+import javax.annotation.Nonnull;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.IpPrefixEqualCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/L3EPServiceUtil.java
new file mode 100644 (file)
index 0000000..3d26c6f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.ep.provider.impl.util;
+
+import com.google.common.util.concurrent.FutureCallback;
+import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: place for common functionality regarding endpoint tasks
+ */
+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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SubnetInfoKeyDecorator.java
new file mode 100644 (file)
index 0000000..b0c4c6b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.ep.provider.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-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java b/sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/SxpListenerUtil.java
new file mode 100644 (file)
index 0000000..15128c3
--- /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.ep.provider.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.ep.provider.impl.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-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-cfg.yang
new file mode 100644 (file)
index 0000000..ea5ebbb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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
+ */
+
+module sxp-ep-provider-cfg {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-integration:sxp-ep-provider";
+    prefix "sxp-ep-prvd-cfg";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+    import groupbasedpolicy-cfg {prefix gbpcfg; revision-date 2015-11-06; }
+
+    description
+        "This module contains the base YANG definitions for
+          sxf-integration : sxp-ep-provider impl configuration.";
+
+    revision "2016-07-22" {
+        description
+            "Initial revision.";
+    }
+
+    identity sxp-ep-provider-impl {
+        description
+            "sxp-ep-provider impl module";
+
+        base "config:module-type";
+        config:java-name-prefix SxpEpProviderProvider;
+    }
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case sxp-ep-provider-impl {
+            when "/config:modules/config:module/config:type = 'sxp-ep-provider-impl'";
+
+            //wires in the data-broker service
+            container data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-async-data-broker;
+                    }
+                }
+            }
+            //RPC Registry
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+            //Domain specific registry
+            container domain-specific-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity gbpcfg:domain-specific-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang b/sxp-integration/sxp-ep-provider/src/main/yang/sxp-ep-provider-model.yang
new file mode 100644 (file)
index 0000000..0391eb0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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
+ */
+
+module sxp-ep-provider-model {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:sxp-ep-provider:model";
+    prefix "sxp-ep-prvd-model";
+
+    import sxp-database { prefix sxp-database; revision-date 2016-03-08; }
+    import gbp-common { prefix gbp-common; revision-date 2014-04-21; }
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import forwarding { prefix forwarding; revision-date 2016-04-27; }
+    import base-endpoint { prefix base-edpoint; revision-date 2016-04-27; }
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
+    import renderer { prefix renderer; revision-date 2015-11-03; }
+
+    description
+        "This module contains the YANG definitions for
+          sxp-ep-provider implementation.";
+
+    revision "2016-03-02" {
+        description
+            "Initial revision.";
+    }
+
+    container sxp-ep-mapper {
+        description "root point for endpoint templates";
+
+        list endpoint-policy-template-by-sgt {
+            key sgt;
+            leaf sgt {
+                type sxp-database:sgt;
+                description
+                    "SGT for which this endpoint template is used";
+            }
+            leaf tenant {
+               type gbp-common:tenant-id;
+               mandatory true;
+               description
+                    "The tenant of this endpoint";
+            }
+            leaf-list endpoint-groups {
+               type gbp-common:endpoint-group-id;
+               min-elements 1;
+               description
+                    "The groups associated with this endpoint";
+            }
+            leaf-list conditions {
+               type gbp-common:condition-name;
+               description
+                    "The conditions associated with this endpoint";
+            }
+        }
+
+        list endpoint-forwarding-template-by-subnet {
+            description "If the IP from IP/SGT binding is inside of ip-prefix then
+                the endpoint will be in the l3-context.";
+            key ip-prefix;
+            leaf ip-prefix {
+                type inet:ip-prefix;
+                description
+                    "The IP prefix where an endpoint can be connected.";
+            }
+            leaf l3-context {
+               type gbp-common:context-id;
+               mandatory true;
+               description
+                    "The context for the endpoint's layer 3 address";
+            }
+            container network-containment {
+                description
+                            "The network domain associated with this endpoint's fowarding
+                            context.";
+                uses forwarding:network-domain-key;
+            }
+        }
+    }
+}
diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEndpointAugmentorImplTest.java
new file mode 100644 (file)
index 0000000..cf6c8ec
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.ep.provider.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.dao.EpPolicyTemplateValueKeyFactory;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ * Test for {@link SxpEndpointAugmentorImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SxpEndpointAugmentorImplTest {
+
+    @Mock
+    private ReadableByKey<EpPolicyTemplateValueKey, EndpointPolicyTemplateBySgt> epPolicyDao;
+    @Spy
+    private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory(
+            EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+    @Captor
+    private ArgumentCaptor<EpPolicyTemplateValueKey> keyCapt;
+
+    private SxpEndpointAugmentorImpl augmetor;
+
+    @Before
+    public void setUp() throws Exception {
+        augmetor = new SxpEndpointAugmentorImpl(epPolicyDao, keyFactory);
+    }
+
+    @Test
+    public void testBuildAddressEndpointWithLocationAugmentation() throws Exception {
+        final TenantId tenantId = new TenantId("tn1");
+        final AddressEndpoint endpoint = new AddressEndpointBuilder()
+                .setTenant(tenantId)
+                .setCondition(buildConditions(new String[]{"cn2", "cn1"}))
+                .setEndpointGroup(buildEndpointGroupIds(new String[]{"epg2", "epg1"}))
+                .build();
+
+        Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.<EndpointPolicyTemplateBySgt>any());
+        final List<ConditionName> conditions = buildConditions(new String[]{"cn1", "cn2"});
+        final List<EndpointGroupId> endpointGroupIds = buildEndpointGroupIds(new String[]{"epg1", "epg2"});
+        final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder()
+                .setTenant(tenantId)
+                .setEndpointGroups(endpointGroupIds)
+                .setConditions(conditions)
+                .setSgt(new Sgt(42))
+                .build();
+
+        Mockito.when(epPolicyDao.readBy(keyCapt.capture())).thenReturn(Collections.singletonList(epPolicyTemplate));
+
+        final Map.Entry<Class<? extends Augmentation<AddressEndpointWithLocation>>, Augmentation<AddressEndpointWithLocation>>
+                augmentationEntry = augmetor.buildAddressEndpointWithLocationAugmentation(endpoint);
+
+//        Assert.assertEquals(AddressEndpointWithLocationAug.class, augmentationEntry.getKey());
+//        Assert.assertTrue(DataObject.class.isAssignableFrom(augmentationEntry.getValue().getClass()));
+//        Assert.assertEquals(AddressEndpointWithLocationAug.class, ((DataObject) augmentationEntry.getValue()).getImplementedInterface());
+//        Assert.assertEquals(42, ((AddressEndpointWithLocationAug) augmentationEntry.getValue()).getSgt().getValue().intValue());
+
+        final EpPolicyTemplateValueKey keyValue = keyCapt.getValue();
+        Assert.assertEquals(tenantId, keyValue.getTenantId());
+        Assert.assertEquals(endpointGroupIds, keyValue.getEpgId());
+        Assert.assertEquals(conditions, keyValue.getConditionName());
+    }
+
+    private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
+        final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
+        for (String epgId : names) {
+            endpointGroupIds.add(new EndpointGroupId(epgId));
+        }
+        return endpointGroupIds;
+    }
+
+    private static List<ConditionName> buildConditions(final String[] names) {
+        final List<ConditionName> conditions = new ArrayList<>();
+        for (String condition : names) {
+            conditions.add(new ConditionName(condition));
+        }
+        return conditions;
+    }
+
+    @Test
+    public void testBuildAddressEndpointAugmentation() throws Exception {
+        final AddressEndpointReg endpoint = new AddressEndpointRegBuilder().build();
+        Assert.assertNull(augmetor.buildAddressEndpointAugmentation(endpoint));
+    }
+
+    @Test
+    public void testBuildContainmentEndpointAugmentation() throws Exception {
+        final ContainmentEndpointReg endpoint = new ContainmentEndpointRegBuilder().build();
+        Assert.assertNull(augmetor.buildContainmentEndpointAugmentation(endpoint));
+    }
+
+    @Test
+    public void testBuildContainmentEndpointWithLocationAugmentation() throws Exception {
+        final ContainmentEndpoint endpoint = new ContainmentEndpointBuilder().build();
+        Assert.assertNull(augmetor.buildContainmentEndpointWithLocationAugmentation(endpoint));
+    }
+}
\ No newline at end of file
diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpMapperReactorImplTest.java
new file mode 100644 (file)
index 0000000..777bfd6
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.ep.provider.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+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.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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.endpoint.forwarding.template.by.subnet.NetworkContainment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link SxpMapperReactorImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SxpMapperReactorImplTest {
+
+    private static final IpPrefix IP_PREFIX = new IpPrefix(new Ipv4Prefix("10.11.12.1/32"));
+
+    @Mock
+    private BaseEndpointService l3EndpointService;
+    @Mock
+    private EndpointPolicyTemplateBySgt epPolicyTemplate;
+    @Mock
+    private MasterDatabaseBinding masterDBBinding;
+    @Mock
+    private EndpointForwardingTemplateBySubnet epForwardingTemplate;
+    @Mock
+    private NetworkContainment networkContainment;
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private ReadOnlyTransaction rTx;
+
+    private SxpMapperReactorImpl sxpMapperReactor;
+
+    @Before
+    public void setUp() throws Exception {
+        sxpMapperReactor = new SxpMapperReactorImpl(l3EndpointService, dataBroker);
+        Mockito.when(l3EndpointService.registerEndpoint(Matchers.<RegisterEndpointInput>any()))
+                .thenReturn(RpcResultBuilder.<Void>success().buildFuture());
+        Mockito.when(masterDBBinding.getIpPrefix()).thenReturn(IP_PREFIX);
+        Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
+        Mockito.when(rTx.read(Matchers.same(LogicalDatastoreType.OPERATIONAL),
+                Matchers.<InstanceIdentifier<AddressEndpoint>>any())).thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
+        Mockito.when(epForwardingTemplate.getNetworkContainment()).thenReturn(networkContainment);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        Mockito.verifyNoMoreInteractions(l3EndpointService);
+    }
+
+    @Test
+    public void testProcessTemplatesAndSxpMasterDB() throws Exception {
+        Mockito.when(epForwardingTemplate.getIpPrefix()).thenReturn(IP_PREFIX);
+        sxpMapperReactor.processTemplatesAndSxpMasterDB(epPolicyTemplate, epForwardingTemplate, masterDBBinding);
+        Mockito.verify(l3EndpointService).registerEndpoint(Matchers.<RegisterEndpointInput>any());
+    }
+}
\ No newline at end of file
diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPForwardingTemplateDaoImplTest.java
new file mode 100644 (file)
index 0000000..6b9e9b2
--- /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.ep.provider.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.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapperBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link EPForwardingTemplateDaoImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EPForwardingTemplateDaoImplTest {
+
+    public static final InstanceIdentifier<SxpEpMapper> SXP_MAPPER_PATH = InstanceIdentifier.create(SxpEpMapper.class);
+    private static final IpPrefix KEY_1 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+    private final SxpEpMapper 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 SxpEpMapperBuilder()
+                .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<SxpEpMapper>>any())).thenReturn(
+                Futures.<Optional<SxpEpMapper>, ReadFailedException>immediateCheckedFuture(Optional.<SxpEpMapper>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<SxpEpMapper>>any())).thenReturn(
+                Futures.<Optional<SxpEpMapper>, 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<SxpEpMapper> readPath = dao.buildReadPath(KEY_1);
+        Assert.assertEquals(SXP_MAPPER_PATH, readPath);
+    }
+}
\ No newline at end of file
diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoImplTest.java
new file mode 100644 (file)
index 0000000..5edeea1
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * 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.ep.provider.impl.dao;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+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 org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+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.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.SxpEpMapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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;
+    @Spy
+    private EpPolicyTemplateValueKeyFactory keyFactory = new EpPolicyTemplateValueKeyFactory(
+            EPTemplateUtil.createEndpointGroupIdOrdering(), EPTemplateUtil.createConditionNameOrdering());
+    @Captor
+    ArgumentCaptor<Sgt> sgtCapt;
+    @Captor
+    ArgumentCaptor<EndpointPolicyTemplateBySgt> epPolicyTemplateCapt;
+
+    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, keyFactory);
+    }
+
+    @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(cachedDao.isEmpty()).thenReturn(true);
+        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)));
+        Mockito.doCallRealMethod().when(keyFactory).sortValueKeyLists(Matchers.<EndpointPolicyTemplateBySgt>any());
+
+        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(SxpEpMapper.class)
+                        .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(KEY_1));
+
+        final InstanceIdentifier<EndpointPolicyTemplateBySgt> readPath = dao.buildReadPath(KEY_1);
+        Assert.assertEquals(expectedPath, readPath);
+    }
+
+    @Test
+    public void testReadBy_single() throws Exception {
+        final EpPolicyTemplateValueKey key = new EpPolicyTemplateValueKey(new TenantId("tn1"),
+                buildEndpointGroupIds(new String[]{"epg1", "epg2"}),
+                buildConditions(new String[]{"cn1", "cn2"}));
+
+        Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.<EndpointPolicyTemplateBySgt>any());
+
+        Mockito.when(cachedDao.values()).thenReturn(Lists.newArrayList(
+                createEpPolicytemplate(new Sgt(1), new String[]{"cn2", "cn1"}, new String[]{"epg1", "epg2"}, "tn1"),
+                createEpPolicytemplate(new Sgt(2), new String[]{"cn1", "cn2"}, new String[]{"epg2", "epg1"}, "tn1"),
+                createEpPolicytemplate(new Sgt(3), new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1"),
+                createEpPolicytemplate(new Sgt(4), new String[]{"cn1", "cn2"}, new String[]{"epg1", "epg2"}, "tn1")
+        ));
+
+        final Collection<EndpointPolicyTemplateBySgt> policyTemplates = dao.readBy(key);
+        Assert.assertEquals(1, policyTemplates.size());
+        Assert.assertEquals(4, Iterables.getFirst(policyTemplates, null).getSgt().getValue().intValue());
+    }
+
+    @Test
+    public void testRead_unsortedLists() throws Exception {
+        final EndpointPolicyTemplateBySgt epPolicytemplateUnsorted = createEpPolicytemplate(new Sgt(1),
+                new String[]{"cn2", "cn1"}, new String[]{"epg2", "epg1"}, "tn1");
+
+        Mockito.doCallRealMethod().when(keyFactory).createKeyWithDefaultOrdering(Matchers.<EndpointPolicyTemplateBySgt>any());
+
+        Mockito.when(cachedDao.find(Matchers.<Sgt>any())).thenReturn(
+                Optional.<EndpointPolicyTemplateBySgt>absent());
+        Mockito.when(cachedDao.isEmpty()).thenReturn(true);
+        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(epPolicytemplateUnsorted)));
+
+        dao.read(new Sgt(1));
+
+        Mockito.verify(cachedDao).update(sgtCapt.capture(), epPolicyTemplateCapt.capture());
+        Mockito.verify(cachedDao).find(sgtCapt.capture());
+
+        Assert.assertEquals(1, sgtCapt.getValue().getValue().intValue());
+        final EndpointPolicyTemplateBySgt template = epPolicyTemplateCapt.getValue();
+        Assert.assertEquals(1, template.getSgt().getValue().intValue());
+        Assert.assertEquals("tn1", template.getTenant().getValue());
+        Assert.assertEquals(buildEndpointGroupIds(new String[]{"epg1", "epg2"}), template.getEndpointGroups());
+        Assert.assertEquals(buildConditions(new String[]{"cn1", "cn2"}), template.getConditions());
+    }
+
+
+    private EndpointPolicyTemplateBySgt createEpPolicytemplate(final Sgt sgt, final String[] conditionNames,
+                                                               final String[] epgIds, final String tenant) {
+        return new EndpointPolicyTemplateBySgtBuilder()
+                .setSgt(sgt)
+                .setEndpointGroups(buildEndpointGroupIds(epgIds))
+                .setConditions(buildConditions(conditionNames))
+                .setTenant(new TenantId(tenant))
+                .build();
+    }
+
+    private static List<EndpointGroupId> buildEndpointGroupIds(final String[] names) {
+        final List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
+        for (String epgId : names) {
+            endpointGroupIds.add(new EndpointGroupId(epgId));
+        }
+        return endpointGroupIds;
+    }
+
+    private static List<ConditionName> buildConditions(final String[] names) {
+        final List<ConditionName> conditions = new ArrayList<>();
+        for (String condition : names) {
+            conditions.add(new ConditionName(condition));
+        }
+        return conditions;
+    }
+}
\ No newline at end of file
diff --git a/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/MasterDatabaseBindingDaoImplTest.java
new file mode 100644 (file)
index 0000000..d549367
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.ep.provider.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.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.sxp.core.Configuration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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.network.topology.topology.node.SxpDomainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainBuilder;
+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()
+                                .setSxpDomains(new SxpDomainsBuilder()
+                                        .setSxpDomain(Collections.singletonList(new SxpDomainBuilder()
+                                                .setDomainName("global")
+                                                .setMasterDatabase(new MasterDatabaseBuilder()
+                                                        .setMasterDatabaseBinding(Lists.newArrayList(MASTER_DB_BINDING_VALUE))
+                                                        .build())
+                                                .build()))
+                                        .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(cachedDao.isEmpty()).thenReturn(true);
+        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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoEPForwardingTemplateImplTest.java
new file mode 100644 (file)
index 0000000..7aa5458
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.ep.provider.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.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/SimpleCachedDaoImplTest.java
new file mode 100644 (file)
index 0000000..80ca279
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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.ep.provider.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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPForwardingTemplateListenerImplTest.java
new file mode 100644 (file)
index 0000000..f30b1a2
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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.ep.provider.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.ClusteredDataTreeChangeListener;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * 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 DSAsyncDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateDao;
+    @Mock
+    private ListenerRegistration<? extends EPTemplateListener> listenerRegistration;
+    @Mock
+    private DataTreeModification<EndpointForwardingTemplateBySubnet> dataTreeModification;
+    @Mock
+    private DataObjectModification<EndpointForwardingTemplateBySubnet> dataObjectModification;
+
+    private EPForwardingTemplateListenerImpl listener;
+    public static final Sgt SGT = new Sgt(1);
+    public static final EndpointPolicyTemplateBySgt EP_POLICY_TEMPLATE = new EndpointPolicyTemplateBySgtBuilder()
+            .setSgt(SGT)
+            .build();
+
+    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.<ClusteredDataTreeChangeListener>any())).thenReturn(listenerRegistration);
+        listener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBBindingDao, epPolicyTemplateDao);
+    }
+
+    @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 IpPrefix ipPrefix = buildIpPrefix("1.2.3.4/32");
+        final MasterDatabaseBinding masterDBBinding = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(SGT)
+                .setIpPrefix(ipPrefix)
+                .build();
+        Mockito.when(masterDBBindingDao.read(Matchers.<IpPrefix>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(masterDBBinding)));
+        Mockito.when(epPolicyTemplateDao.read(Matchers.<Sgt>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(EP_POLICY_TEMPLATE)));
+        Mockito.when(sxpMapper.processTemplatesAndSxpMasterDB(Matchers.<EndpointPolicyTemplateBySgt>any(),
+                Matchers.<EndpointForwardingTemplateBySubnet>any(),Matchers.<MasterDatabaseBinding>any())).thenReturn(
+                RpcResultBuilder.success((Void) null).buildFuture());
+
+        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+        final InOrder inOrder = Mockito.inOrder(masterDBBindingDao, simpleCachedDao, epPolicyTemplateDao, sxpMapper);
+        inOrder.verify(simpleCachedDao).update(IP_PREFIX_TMPL, EP_FW_TEMPLATE_VALUE);
+        inOrder.verify(masterDBBindingDao).read(IP_PREFIX_TMPL);
+        inOrder.verify(epPolicyTemplateDao).read(SGT);
+        inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_POLICY_TEMPLATE, EP_FW_TEMPLATE_VALUE, masterDBBinding);
+        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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/EPPolicyTemplateListenerImplTest.java
new file mode 100644 (file)
index 0000000..2caf570
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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.ep.provider.impl.listen;
+
+import com.google.common.base.Optional;
+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.ClusteredDataTreeChangeListener;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.ReadableAsyncByKey;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * 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 static final IpPrefix IP_PREFIX_1 = new IpPrefix(new Ipv4Prefix("1.2.3.4/32"));
+    private static final IpPrefix IP_PREFIX_2 = new IpPrefix(new Ipv4Prefix("1.2.3.5/32"));
+    private final EndpointPolicyTemplateBySgt EP_PL_TEMPLATE_VALUE;
+
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private SxpMapperReactor sxpMapper;
+    @Mock
+    private SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> simpleCachedDao;
+    @Mock
+    private DSAsyncDao<IpPrefix, EndpointForwardingTemplateBySubnet> epForwardingTemplateDao;
+    @Mock
+    private ReadableAsyncByKey<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.<ClusteredDataTreeChangeListener>any())).thenReturn(listenerRegistration);
+        listener = new EPPolicyTemplateListenerImpl(dataBroker, sxpMapper, simpleCachedDao, masterDBDao, epForwardingTemplateDao);
+    }
+
+    @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 masterDBBinding1 = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(SGT_1)
+                .setIpPrefix(IP_PREFIX_1)
+                .build();
+        final MasterDatabaseBinding masterDBBinding2 = new MasterDatabaseBindingBuilder()
+                .setSecurityGroupTag(SGT_1)
+                .setIpPrefix(IP_PREFIX_2)
+                .build();
+
+        final EndpointForwardingTemplateBySubnet epForwardingTemplate1 = new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(IP_PREFIX_1)
+                .build();
+        final EndpointForwardingTemplateBySubnet epForwardingTemplate2 = new EndpointForwardingTemplateBySubnetBuilder()
+                .setIpPrefix(IP_PREFIX_2)
+                .build();
+
+        Mockito.when(masterDBDao.readBy(Matchers.<Sgt>any())).thenReturn(
+                Futures.immediateFuture(Lists.newArrayList(masterDBBinding1, masterDBBinding2)));
+        Mockito.when(epForwardingTemplateDao.read(Matchers.<IpPrefix>any())).thenReturn(
+                Futures.immediateFuture(Optional.of(epForwardingTemplate1)),
+                Futures.immediateFuture(Optional.of(epForwardingTemplate2)));
+        Mockito.when(sxpMapper.processTemplatesAndSxpMasterDB(Matchers.<EndpointPolicyTemplateBySgt>any(),
+                Matchers.<EndpointForwardingTemplateBySubnet>any(), Matchers.<MasterDatabaseBinding>any())).thenReturn(
+                RpcResultBuilder.success((Void) null).buildFuture());
+
+        listener.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+        final InOrder inOrder = Mockito.inOrder(masterDBDao, simpleCachedDao, epForwardingTemplateDao, sxpMapper);
+        inOrder.verify(simpleCachedDao).update(SGT_1, EP_PL_TEMPLATE_VALUE);
+        inOrder.verify(masterDBDao).readBy(SGT_1);
+        inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX_1);
+        inOrder.verify(epForwardingTemplateDao).read(IP_PREFIX_2);
+        inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_PL_TEMPLATE_VALUE, epForwardingTemplate1, masterDBBinding1);
+        inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(EP_PL_TEMPLATE_VALUE, epForwardingTemplate2, masterDBBinding2);
+        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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/listen/MasterDatabaseBindingListenerImplTest.java
new file mode 100644 (file)
index 0000000..49b0f0a
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.ep.provider.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.ClusteredDataTreeChangeListener;
+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.ep.provider.impl.DSAsyncDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.EPTemplateListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.MasterDatabaseBindingListener;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
+import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SxpMapperReactor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.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.network.topology.topology.node.SxpDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey;
+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(SxpDomains.class)
+                    .child(SxpDomain.class, new SxpDomainKey("global"))
+                    .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.<ClusteredDataTreeChangeListener>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(epForwardingTemplateDao).read(IP_PREFIX);
+        inOrder.verify(sxpMapper).processTemplatesAndSxpMasterDB(epPolicyTemplate, 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-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java b/sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/util/EPTemplateUtilTest.java
new file mode 100644 (file)
index 0000000..63fe541
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.ep.provider.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.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+
+/**
+ * Test for {@link EPTemplateUtil}.
+ */
+public class EPTemplateUtilTest {
+
+    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(EPTemplateUtil.isPlain(IP_PREFIX_24));
+        Assert.assertTrue(EPTemplateUtil.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 = EPTemplateUtil.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
diff --git a/sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml b/sxp-integration/sxp-ep-provider/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..024a8db
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+    <appender name="console" class="org.apache.log4j.ConsoleAppender">\r
+        <layout class="org.apache.log4j.PatternLayout">\r
+            <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n"/>\r
+        </layout>\r
+        <!--         <param name="Threshold" value="DEBUG" /> -->\r
+    </appender>\r
+\r
+    <logger name="org.opendaylight.groupbasedpolicy.sxp.mapper" additivity="false">\r
+        <level value="DEBUG"/>\r
+        <appender-ref ref="console"/>\r
+    </logger>\r
+\r
+    <logger name="org.opendaylight.groupbasedpolicy.sxp.mapper.impl.dao" additivity="false">\r
+        <level value="TRACE"/>\r
+        <appender-ref ref="console"/>\r
+    </logger>\r
+\r
+    <root>\r
+        <priority value="INFO"/>\r
+        <appender-ref ref="console"/>\r
+    </root>\r
+</log4j:configuration>\r