Introduced Renderer Manager 88/38288/18
authorMartin Sunal <msunal@cisco.com>
Mon, 2 May 2016 17:05:20 +0000 (19:05 +0200)
committerMartin Sunal <msunal@cisco.com>
Wed, 18 May 2016 23:09:36 +0000 (01:09 +0200)
Renderer manager dispatches policy configuration among endoints
to renderers.
Renderer manager gets data notifications about:
- Endoints (base-endpoint.yang)
- EndpointLocations (base-endpoint.yang)
- ResolvedPolicies (resolved-policy.yang)
- Forwarding (forwarding.yang)

Based on data from notifications it creates a configuration for renderers.
Configuration is stored to CONF DS as Renderers (renderer.yang)

Configuration is sign with version which is incremented by every change.
All rendrers are suposed to be on the same version. Renderer manager waits
for all renderers to respond with version update in OPER DS. After a version
of every renderer in OPER DS is same as version in CONF DS, renderer manager
moves to the next configuration with incremented version.

Change-Id: I475b357d5d60444dc359bc400c567d9d0e36238f
Signed-off-by: Martin Sunal <msunal@cisco.com>
19 files changed:
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/GroupbasedpolicyModule.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/AddressEndpointUtils.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ContainmentEndpointUtils.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointInfo.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationInfo.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationUtils.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ResolvedPolicyInfo.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointLocationsListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointsListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ForwardingListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/RenderersListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ResolvedPoliciesListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/yang/model/renderer.yang
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerDataBrokerTest.java [new file with mode: 0644]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerTest.java [new file with mode: 0644]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/TestDataFactory.java [new file with mode: 0644]

index 779a5afe70ce34743c5df8d84cca00bad32ffcf5..3ba11fa66ed98de515637835653c3ba748c4c626 100644 (file)
@@ -12,6 +12,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
 import org.opendaylight.groupbasedpolicy.location.resolver.LocationResolver;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
 import org.opendaylight.groupbasedpolicy.sf.SubjectFeatureDefinitionProvider;
 import org.opendaylight.groupbasedpolicy.sf.SupportedActionDefinitionListener;
 import org.opendaylight.groupbasedpolicy.sf.SupportedClassifierDefinitionListener;
@@ -62,12 +63,14 @@ public class GroupbasedpolicyModule extends org.opendaylight.controller.config.y
         private final SupportedClassifierDefinitionListener supportedClassifierDefinitionListener;
         private final SupportedActionDefinitionListener supportedActionDefinitionListener;
         private final LocationResolver locationResolver;
+        private final RendererManager rendererManager;
 
         Instance(DataBroker dataProvider, PolicyValidatorRegistry validatorRegistry) throws TransactionCommitFailedException {
             sfdp = new SubjectFeatureDefinitionProvider(dataProvider);
             supportedClassifierDefinitionListener = new SupportedClassifierDefinitionListener(dataProvider, validatorRegistry);
             supportedActionDefinitionListener = new SupportedActionDefinitionListener(dataProvider);
             locationResolver = new LocationResolver(dataProvider);
+            rendererManager = new RendererManager(dataProvider);
         }
 
         @Override
@@ -76,6 +79,7 @@ public class GroupbasedpolicyModule extends org.opendaylight.controller.config.y
             supportedClassifierDefinitionListener.close();
             supportedActionDefinitionListener.close();
             locationResolver.close();
+            rendererManager.close();
         }
     }
 
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/AddressEndpointUtils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/AddressEndpointUtils.java
new file mode 100644 (file)
index 0000000..1675bb8
--- /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.renderer;
+
+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.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.endpoints.PeerExternalEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+
+public class AddressEndpointUtils {
+
+    public static RendererEndpointKey toRendererEpKey(AddressEndpointKey rendererAdrEpKey) {
+        return new RendererEndpointKey(rendererAdrEpKey.getAddress(), rendererAdrEpKey.getAddressType(),
+                rendererAdrEpKey.getContextId(), rendererAdrEpKey.getContextType());
+    }
+
+    public static PeerEndpointKey toPeerEpKey(AddressEndpointKey peerAdrEpKey) {
+        return new PeerEndpointKey(peerAdrEpKey.getAddress(), peerAdrEpKey.getAddressType(),
+                peerAdrEpKey.getContextId(), peerAdrEpKey.getContextType());
+    }
+
+    public static PeerExternalEndpointKey toPeerExtEpKey(AddressEndpointKey peerAdrEpKey) {
+        return new PeerExternalEndpointKey(peerAdrEpKey.getAddress(), peerAdrEpKey.getAddressType(),
+                peerAdrEpKey.getContextId(), peerAdrEpKey.getContextType());
+    }
+
+    public static AddressEndpointKey fromRendererEpKey(RendererEndpointKey rendererEpKey) {
+        return new AddressEndpointKey(rendererEpKey.getAddress(), rendererEpKey.getAddressType(),
+                rendererEpKey.getContextId(), rendererEpKey.getContextType());
+    }
+
+    public static AddressEndpointKey fromPeerEpKey(PeerEndpointKey peerEpKey) {
+        return new AddressEndpointKey(peerEpKey.getAddress(), peerEpKey.getAddressType(), peerEpKey.getContextId(),
+                peerEpKey.getContextType());
+    }
+
+    public static AddressEndpointKey fromPeerExtEpKey(PeerExternalEndpointKey peerExtEpKey) {
+        return new AddressEndpointKey(peerExtEpKey.getAddress(), peerExtEpKey.getAddressType(),
+                peerExtEpKey.getContextId(), peerExtEpKey.getContextType());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ContainmentEndpointUtils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ContainmentEndpointUtils.java
new file mode 100644 (file)
index 0000000..86a5d0c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.renderer;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.containment.endpoints.PeerExternalContainmentEndpointKey;
+
+public class ContainmentEndpointUtils {
+
+    public static PeerExternalContainmentEndpointKey toPeerExtContEpKey(ContainmentEndpointKey peerContEpKey) {
+        return new PeerExternalContainmentEndpointKey(peerContEpKey.getContextId(), peerContEpKey.getContextType());
+    }
+
+    public static ContainmentEndpointKey fromPeerExtContEpKey(PeerExternalContainmentEndpointKey peerExtContEpKey) {
+        return new ContainmentEndpointKey(peerExtContEpKey.getContextId(), peerExtContEpKey.getContextType());
+    }
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointInfo.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointInfo.java
new file mode 100644 (file)
index 0000000..b8ef7c0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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.renderer;
+
+import java.util.Set;
+
+import org.opendaylight.groupbasedpolicy.dto.EpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+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.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.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.ImmutableSetMultimap;
+
+public class EndpointInfo {
+
+    private final ImmutableMap<AddressEndpointKey, AddressEndpoint> addressEpByKey;
+    private final ImmutableMap<ContainmentEndpointKey, ContainmentEndpoint> containmentEpByKey;
+    private final ImmutableSetMultimap<EpgKey, AddressEndpointKey> addressEpsByEpg;
+    private final ImmutableSetMultimap<EpgKey, ContainmentEndpointKey> containmentEpsByEpg;
+
+    public EndpointInfo(Endpoints endpoints) {
+        if (endpoints.getAddressEndpoints() == null || endpoints.getAddressEndpoints().getAddressEndpoint() == null) {
+            addressEpByKey = ImmutableMap.of();
+            addressEpsByEpg = ImmutableSetMultimap.of();
+        } else {
+            com.google.common.collect.ImmutableMap.Builder<AddressEndpointKey, AddressEndpoint> addressEpsByKeyBuilder =
+                    ImmutableMap.builder();
+            com.google.common.collect.ImmutableSetMultimap.Builder<EpgKey, AddressEndpointKey> addressEpsByEpgBuilder =
+                    ImmutableSetMultimap.builder();
+            com.google.common.collect.ImmutableMultimap.Builder<Set<EpgKey>, AddressEndpointKey> addressEpsByEpgsBuilder =
+                    ImmutableMultimap.builder();
+            for (AddressEndpoint ep : endpoints.getAddressEndpoints().getAddressEndpoint()) {
+                addressEpsByKeyBuilder.put(ep.getKey(), ep);
+                Builder<EpgKey> epgsBuilder = ImmutableSet.builder();
+                for (EndpointGroupId epgId : ep.getEndpointGroup()) {
+                    EpgKey epgKey = new EpgKeyDto(epgId, ep.getTenant());
+                    addressEpsByEpgBuilder.put(epgKey, ep.getKey());
+                    epgsBuilder.add(epgKey);
+                }
+                addressEpsByEpgsBuilder.put(epgsBuilder.build(), ep.getKey());
+            }
+            addressEpByKey = addressEpsByKeyBuilder.build();
+            addressEpsByEpg = addressEpsByEpgBuilder.build();
+        }
+        if (endpoints.getContainmentEndpoints() == null
+                || endpoints.getContainmentEndpoints().getContainmentEndpoint() == null) {
+            containmentEpByKey = ImmutableMap.of();
+            containmentEpsByEpg = ImmutableSetMultimap.of();
+        } else {
+            com.google.common.collect.ImmutableSetMultimap.Builder<EpgKey, ContainmentEndpointKey> containmentEpsByEpgBuilder =
+                    ImmutableSetMultimap.builder();
+            com.google.common.collect.ImmutableMap.Builder<ContainmentEndpointKey, ContainmentEndpoint> containmentEpsByKeyBuilder =
+                    ImmutableMap.builder();
+            com.google.common.collect.ImmutableMultimap.Builder<Set<EpgKey>, ContainmentEndpointKey> containmentEpsByEpgsBuilder =
+                    ImmutableMultimap.builder();
+            for (ContainmentEndpoint ep : endpoints.getContainmentEndpoints().getContainmentEndpoint()) {
+                containmentEpsByKeyBuilder.put(ep.getKey(), ep);
+                Builder<EpgKey> epgsBuilder = ImmutableSet.builder();
+                for (EndpointGroupId epgId : ep.getEndpointGroup()) {
+                    EpgKey epgKey = new EpgKeyDto(epgId, ep.getTenant());
+                    containmentEpsByEpgBuilder.put(epgKey, ep.getKey());
+                    epgsBuilder.add(epgKey);
+                }
+                containmentEpsByEpgsBuilder.put(epgsBuilder.build(), ep.getKey());
+            }
+            containmentEpByKey = containmentEpsByKeyBuilder.build();
+            containmentEpsByEpg = containmentEpsByEpgBuilder.build();
+        }
+    }
+
+    public Optional<AddressEndpoint> getEndpoint(AddressEndpointKey key) {
+        return Optional.fromNullable(addressEpByKey.get(key));
+    }
+
+    public Optional<ContainmentEndpoint> getContainmentEndpoint(ContainmentEndpointKey key) {
+        return Optional.fromNullable(containmentEpByKey.get(key));
+    }
+
+    public ImmutableSet<AddressEndpointKey> findAddressEpsWithEpg(EpgKey epg) {
+        return addressEpsByEpg.get(epg);
+    }
+
+    public ImmutableSet<ContainmentEndpointKey> findContainmentEpsWithEpg(EpgKey epg) {
+        return containmentEpsByEpg.get(epg);
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationInfo.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationInfo.java
new file mode 100644 (file)
index 0000000..a961e1e
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationKey;
+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.endpoints.containment.endpoints.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+public class EndpointLocationInfo {
+
+    private final ImmutableMultimap<InstanceIdentifier<?>, AddressEndpointLocation> endpointsByAbsNodeLocation;
+    private final ImmutableMap<AddressEndpointKey, AddressEndpointLocation> adrEpLocByAdrEpKey;
+    private final ImmutableMap<ContainmentEndpointKey, ContainmentEndpointLocation> contEpLocBycontEpKey;
+
+    public EndpointLocationInfo(EndpointLocations epLocations) {
+        List<AddressEndpointLocation> addressEndpointLocations = epLocations.getAddressEndpointLocation();
+        endpointsByAbsNodeLocation = EndpointLocationUtils.resolveEndpointsByAbsoluteNodeLocation(addressEndpointLocations);
+        if (addressEndpointLocations == null) {
+            adrEpLocByAdrEpKey = ImmutableMap.of();
+        } else {
+            com.google.common.collect.ImmutableMap.Builder<AddressEndpointKey, AddressEndpointLocation> adrEpLocByAdrEpKeyBuilder =
+                    ImmutableMap.builder();
+            for (AddressEndpointLocation adrEpLoc : addressEndpointLocations) {
+                adrEpLocByAdrEpKeyBuilder.put(toAdrEpKey(adrEpLoc.getKey()), adrEpLoc);
+            }
+            adrEpLocByAdrEpKey = adrEpLocByAdrEpKeyBuilder.build();
+        }
+        List<ContainmentEndpointLocation> containmentEndpointLocations = epLocations.getContainmentEndpointLocation();
+        if (containmentEndpointLocations == null) {
+            contEpLocBycontEpKey = ImmutableMap.of();
+        } else {
+            com.google.common.collect.ImmutableMap.Builder<ContainmentEndpointKey, ContainmentEndpointLocation> contEpLocBycontEpKeyBuilder =
+                    ImmutableMap.builder();
+            for (ContainmentEndpointLocation contEpLoc : containmentEndpointLocations) {
+                contEpLocBycontEpKeyBuilder.put(toContEpKey(contEpLoc.getKey()), contEpLoc);
+            }
+            contEpLocBycontEpKey = contEpLocBycontEpKeyBuilder.build();
+        }
+    }
+
+    public Optional<AddressEndpointLocation> getAdressEndpointLocation(AddressEndpointKey epKey) {
+        return Optional.fromNullable(adrEpLocByAdrEpKey.get(epKey));
+    }
+
+    public Optional<ContainmentEndpointLocation> getContainmentEndpointLocation(ContainmentEndpointKey contEpKey) {
+        return Optional.fromNullable(contEpLocBycontEpKey.get(contEpKey));
+    }
+
+    private AddressEndpointKey toAdrEpKey(AddressEndpointLocationKey adrEpLocKey) {
+        return new AddressEndpointKey(adrEpLocKey.getAddress(), adrEpLocKey.getAddressType(),
+                adrEpLocKey.getContextId(), adrEpLocKey.getContextType());
+    }
+
+    private ContainmentEndpointKey toContEpKey(ContainmentEndpointLocationKey contEpLocKey) {
+        return new ContainmentEndpointKey(contEpLocKey.getContextId(), contEpLocKey.getContextType());
+    }
+
+    public Set<InstanceIdentifier<?>> getAllAbsoluteNodeLocations() {
+        return endpointsByAbsNodeLocation.keySet();
+    }
+
+    public ImmutableSet<AddressEndpointKey> getAddressEpsWithAbsoluteNodeLocation(InstanceIdentifier<?> realNodeLocation) {
+        return FluentIterable.from(endpointsByAbsNodeLocation.get(realNodeLocation))
+                .transform(new Function<AddressEndpointLocation, AddressEndpointKey>() {
+
+                    @Override
+                    public AddressEndpointKey apply(AddressEndpointLocation epLoc) {
+                        return new AddressEndpointKey(epLoc.getAddress(),
+                                epLoc.getAddressType(), epLoc.getContextId(), epLoc.getContextType());
+                    }
+                })
+                .toSet();
+    }
+
+    public boolean hasRealLocation(AddressEndpointKey adrEpKey) {
+        AddressEndpointLocation adrEpLoc = adrEpLocByAdrEpKey.get(adrEpKey);
+        if (adrEpLoc == null) {
+            return false;
+        }
+        AbsoluteLocation absLocation = adrEpLoc.getAbsoluteLocation();
+        if (absLocation == null) {
+            return false;
+        }
+        LocationType locationType = absLocation.getLocationType();
+        if (locationType == null) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean hasRelativeLocation(AddressEndpointKey adrEpKey) {
+        AddressEndpointLocation adrEpLoc = adrEpLocByAdrEpKey.get(adrEpKey);
+        if (adrEpLoc == null) {
+            return false;
+        }
+        RelativeLocations relLocations = adrEpLoc.getRelativeLocations();
+        if (relLocations == null) {
+            return false;
+        }
+        List<InternalLocation> locs = relLocations.getInternalLocation();
+        if (locs == null) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean hasRelativeLocation(ContainmentEndpointKey contEpKey) {
+        ContainmentEndpointLocation contEpLoc = contEpLocBycontEpKey.get(contEpKey);
+        if (contEpLoc == null) {
+            return false;
+        }
+        RelativeLocations relLocations = contEpLoc.getRelativeLocations();
+        if (relLocations == null) {
+            return false;
+        }
+        List<InternalLocation> locs = relLocations.getInternalLocation();
+        if (locs == null) {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationUtils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/EndpointLocationUtils.java
new file mode 100644 (file)
index 0000000..6e7f81f
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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.renderer;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCase;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+
+public class EndpointLocationUtils {
+
+    public static ImmutableMultimap<InstanceIdentifier<?>, AddressEndpointLocation> resolveEndpointsByAbsoluteNodeLocation(
+            @Nullable List<AddressEndpointLocation> addressEndpointLocations) {
+        if (addressEndpointLocations == null) {
+            return ImmutableMultimap.of();
+        }
+        Builder<InstanceIdentifier<?>, AddressEndpointLocation> resultBuilder = ImmutableMultimap.builder();
+        for (AddressEndpointLocation epLoc : addressEndpointLocations) {
+            Optional<InstanceIdentifier<?>> potentialAbsIntNodeLocation = resolveAbsoluteInternalNodeLocation(epLoc);
+            if (potentialAbsIntNodeLocation.isPresent()) {
+                resultBuilder.put(potentialAbsIntNodeLocation.get(), epLoc);
+            } else {
+                Optional<InstanceIdentifier<?>> potentialAbsExtNodeMpLocation =
+                        resolveAbsoluteExternalNodeMountPointLocation(epLoc);
+                if (potentialAbsExtNodeMpLocation.isPresent()) {
+                    resultBuilder.put(potentialAbsExtNodeMpLocation.get(), epLoc);
+                }
+            }
+        }
+        return resultBuilder.build();
+    }
+
+    public static Optional<InstanceIdentifier<?>> resolveAbsoluteInternalNodeLocation(AddressEndpointLocation epLoc) {
+        AbsoluteLocation absLoc = epLoc.getAbsoluteLocation();
+        if (absLoc != null) {
+            LocationType locType = absLoc.getLocationType();
+            if (locType instanceof InternalLocationCase) {
+                InternalLocationCase absRegularLoc = (InternalLocationCase) locType;
+                if (absRegularLoc.getInternalNode() != null) {
+                    return Optional.of(absRegularLoc.getInternalNode());
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    public static Optional<InstanceIdentifier<?>> resolveAbsoluteExternalNodeMountPointLocation(
+            AddressEndpointLocation epLoc) {
+        AbsoluteLocation absLoc = epLoc.getAbsoluteLocation();
+        if (absLoc != null) {
+            LocationType locType = absLoc.getLocationType();
+            if (locType instanceof ExternalLocationCase) {
+                ExternalLocationCase realExtLoc = (ExternalLocationCase) locType;
+                if (realExtLoc.getExternalNodeMountPoint() != null) {
+                    return Optional.of(realExtLoc.getExternalNodeMountPoint());
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    public static Optional<InstanceIdentifier<?>> resolveAbsoluteNodeLocation(AddressEndpointLocation epLoc) {
+        if (epLoc.getAbsoluteLocation() == null) {
+            return Optional.absent();
+        }
+        LocationType locType = epLoc.getAbsoluteLocation().getLocationType();
+        if (locType instanceof InternalLocationCase) {
+            InternalLocationCase absLoc = (InternalLocationCase) locType;
+            if (absLoc.getInternalNode() != null) {
+                return Optional.of(absLoc.getInternalNode());
+            }
+        } else if (locType instanceof ExternalLocationCase) {
+            ExternalLocationCase absLoc = (ExternalLocationCase) locType;
+            if (absLoc.getExternalNodeMountPoint() != null) {
+                return Optional.of(absLoc.getExternalNodeMountPoint());
+            }
+        }
+        return Optional.absent();
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java
new file mode 100644 (file)
index 0000000..c3bbf7f
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * 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.renderer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
+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.endpoints.containment.endpoints.ContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.containment.endpoints.PeerExternalContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.endpoints.PeerExternalEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.ForwardingContexts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.ForwardingContextsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroupsBuilder;
+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.AddressEndpointWithLocationBuilder;
+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.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.ContainmentEndpointWithLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.forwarding.contexts.ForwardingContextByTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.forwarding.contexts.ForwardingContextByTenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalContainmentEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalContainmentEndpointWithPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalContainmentEndpointWithPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalEndpointWithPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalEndpointWithPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
+
+public class RendererConfigurationBuilder {
+
+    private final Table<RendererEndpointKey, PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerEp =
+            HashBasedTable.create();
+    private final Table<RendererEndpointKey, PeerExternalEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerExtEp =
+            HashBasedTable.create();
+    private final Table<RendererEndpointKey, PeerExternalContainmentEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerExtCtxEp =
+            HashBasedTable.create();
+    private final Set<AddressEndpointKey> adrEpKeys = new HashSet<>();
+    private final Set<ContainmentEndpointKey> contEpKeys = new HashSet<>();
+    private final Set<PolicyRuleGroupKey> policyRuleGrpKeys = new HashSet<>();
+
+    public void add(RendererEndpointKey rendererEpKey, PeerEndpointKey peerEpKey, PolicyRuleGroupKey ruleGrpKey,
+            EndpointPolicyParticipation rendererEpParticipation) {
+        Set<RuleGroupWithRendererEndpointParticipation> ruleGrpWithRendererEpParticipation =
+                policiesByEpAndPeerEp.get(rendererEpKey, peerEpKey);
+        if (ruleGrpWithRendererEpParticipation == null) {
+            ruleGrpWithRendererEpParticipation = new HashSet<>();
+            policiesByEpAndPeerEp.put(rendererEpKey, peerEpKey, ruleGrpWithRendererEpParticipation);
+            adrEpKeys.add(AddressEndpointUtils.fromRendererEpKey(rendererEpKey));
+            adrEpKeys.add(AddressEndpointUtils.fromPeerEpKey(peerEpKey));
+        }
+        policyRuleGrpKeys.add(ruleGrpKey);
+        ruleGrpWithRendererEpParticipation
+            .add(toRuleGroupWithRendererEndpointParticipation(ruleGrpKey, rendererEpParticipation));
+    }
+
+    public void add(RendererEndpointKey rendererEpKey, PeerExternalEndpointKey peerExtEpKey,
+            PolicyRuleGroupKey ruleGrpKey, EndpointPolicyParticipation rendererEpParticipation) {
+        Set<RuleGroupWithRendererEndpointParticipation> ruleGrpWithRendererEpParticipation =
+                policiesByEpAndPeerExtEp.get(rendererEpKey, peerExtEpKey);
+        if (ruleGrpWithRendererEpParticipation == null) {
+            ruleGrpWithRendererEpParticipation = new HashSet<>();
+            policiesByEpAndPeerExtEp.put(rendererEpKey, peerExtEpKey, ruleGrpWithRendererEpParticipation);
+            adrEpKeys.add(AddressEndpointUtils.fromRendererEpKey(rendererEpKey));
+            adrEpKeys.add(AddressEndpointUtils.fromPeerExtEpKey(peerExtEpKey));
+        }
+        policyRuleGrpKeys.add(ruleGrpKey);
+        ruleGrpWithRendererEpParticipation
+            .add(toRuleGroupWithRendererEndpointParticipation(ruleGrpKey, rendererEpParticipation));
+    }
+
+    public void add(RendererEndpointKey rendererEpKey, PeerExternalContainmentEndpointKey peerExtContainmentEpKey,
+            PolicyRuleGroupKey ruleGrpKey, EndpointPolicyParticipation rendererEpParticipation) {
+        Set<RuleGroupWithRendererEndpointParticipation> ruleGrpWithRendererEpParticipation =
+                policiesByEpAndPeerExtCtxEp.get(rendererEpKey, peerExtContainmentEpKey);
+        if (ruleGrpWithRendererEpParticipation == null) {
+            ruleGrpWithRendererEpParticipation = new HashSet<>();
+            policiesByEpAndPeerExtCtxEp.put(rendererEpKey, peerExtContainmentEpKey, ruleGrpWithRendererEpParticipation);
+            adrEpKeys.add(AddressEndpointUtils.fromRendererEpKey(rendererEpKey));
+            contEpKeys.add(ContainmentEndpointUtils.fromPeerExtContEpKey(peerExtContainmentEpKey));
+        }
+        policyRuleGrpKeys.add(ruleGrpKey);
+        ruleGrpWithRendererEpParticipation
+            .add(toRuleGroupWithRendererEndpointParticipation(ruleGrpKey, rendererEpParticipation));
+    }
+
+    public static RuleGroupWithRendererEndpointParticipation toRuleGroupWithRendererEndpointParticipation(
+            PolicyRuleGroupKey ruleGrpKey, EndpointPolicyParticipation rendererEpParticipation) {
+        return new RuleGroupWithRendererEndpointParticipationBuilder().setTenantId(ruleGrpKey.getTenantId())
+            .setContractId(ruleGrpKey.getContractId())
+            .setSubjectName(ruleGrpKey.getSubjectName())
+            .setRendererEndpointParticipation(rendererEpParticipation)
+            .build();
+    }
+
+    public ImmutableTable<RendererEndpointKey, PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> getPoliciesByEpAndPeerEp() {
+        return ImmutableTable.copyOf(policiesByEpAndPeerEp);
+    }
+
+    public ImmutableTable<RendererEndpointKey, PeerExternalEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> getPoliciesByEpAndPeerExtEp() {
+        return ImmutableTable.copyOf(policiesByEpAndPeerExtEp);
+    }
+
+    public ImmutableTable<RendererEndpointKey, PeerExternalContainmentEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> getPoliciesByEpAndPeerExtConEp() {
+        return ImmutableTable.copyOf(policiesByEpAndPeerExtCtxEp);
+    }
+
+    public ImmutableSet<AddressEndpointKey> getAddressEndpointKeys() {
+        return ImmutableSet.copyOf(adrEpKeys);
+    }
+
+    public ImmutableSet<ContainmentEndpointKey> getContainmentEndpointKeys() {
+        return ImmutableSet.copyOf(contEpKeys);
+    }
+
+    public ImmutableSet<PolicyRuleGroupKey> getPolicyRuleGroupKeys() {
+        return ImmutableSet.copyOf(policyRuleGrpKeys);
+    }
+
+    public @Nonnull RendererEndpoints buildRendererEndpoints() {
+        Map<RendererEndpointKey, RendererEndpointBuilder> rendererEpBuilderByKey = new HashMap<>();
+        for (RendererEndpointKey rendererEpKey : policiesByEpAndPeerEp.rowKeySet()) {
+            RendererEndpointBuilder rendererEpBuilder =
+                    resolveRendererEndpointBuilder(rendererEpKey, rendererEpBuilderByKey);
+            List<PeerEndpointWithPolicy> peerEpsWithPolicy =
+                    toListPeerEndpointWithPolicy(policiesByEpAndPeerEp.row(rendererEpKey));
+            rendererEpBuilder.setPeerEndpointWithPolicy(peerEpsWithPolicy);
+            rendererEpBuilderByKey.put(rendererEpKey, rendererEpBuilder);
+        }
+        for (RendererEndpointKey rendererEpKey : policiesByEpAndPeerExtEp.rowKeySet()) {
+            RendererEndpointBuilder rendererEpBuilder =
+                    resolveRendererEndpointBuilder(rendererEpKey, rendererEpBuilderByKey);
+            List<PeerExternalEndpointWithPolicy> peerExtEpsWithPolicy =
+                    toListPeerExternalEndpointWithPolicy(policiesByEpAndPeerExtEp.row(rendererEpKey));
+            rendererEpBuilder.setPeerExternalEndpointWithPolicy(peerExtEpsWithPolicy);
+            rendererEpBuilderByKey.put(rendererEpKey, rendererEpBuilder);
+        }
+        for (RendererEndpointKey rendererEpKey : policiesByEpAndPeerExtCtxEp.rowKeySet()) {
+            RendererEndpointBuilder rendererEpBuilder =
+                    resolveRendererEndpointBuilder(rendererEpKey, rendererEpBuilderByKey);
+            List<PeerExternalContainmentEndpointWithPolicy> peerExtContEpsWithPolicy =
+                    toListPeerExternalContainmentEndpointWithPolicy(policiesByEpAndPeerExtCtxEp.row(rendererEpKey));
+            rendererEpBuilder.setPeerExternalContainmentEndpointWithPolicy(peerExtContEpsWithPolicy);
+            rendererEpBuilderByKey.put(rendererEpKey, rendererEpBuilder);
+        }
+        List<RendererEndpoint> rendererEps = new ArrayList<>();
+        for (RendererEndpointBuilder builder : rendererEpBuilderByKey.values()) {
+            rendererEps.add(builder.build());
+        }
+        return new RendererEndpointsBuilder().setRendererEndpoint(rendererEps).build();
+    }
+
+    private static RendererEndpointBuilder resolveRendererEndpointBuilder(RendererEndpointKey rendererEpKey,
+            Map<RendererEndpointKey, RendererEndpointBuilder> rendererEpBuilderByKey) {
+        RendererEndpointBuilder rendererEpBuilder = rendererEpBuilderByKey.get(rendererEpKey);
+        if (rendererEpBuilder == null) {
+            rendererEpBuilder = new RendererEndpointBuilder();
+            rendererEpBuilder.setKey(rendererEpKey);
+        }
+        return rendererEpBuilder;
+    }
+
+    private static List<PeerEndpointWithPolicy> toListPeerEndpointWithPolicy(
+            Map<PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByPeerEp) {
+        List<PeerEndpointWithPolicy> peerEpsWithPolicy = new ArrayList<>();
+        for (Entry<PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> entry : policiesByPeerEp
+            .entrySet()) {
+            PeerEndpointKey peerEpKey = entry.getKey();
+            PeerEndpointWithPolicyKey peerEndpointWithPolicyKey = new PeerEndpointWithPolicyKey(peerEpKey.getAddress(),
+                    peerEpKey.getAddressType(), peerEpKey.getContextId(), peerEpKey.getContextType());
+            PeerEndpointWithPolicy peerEndpointWithPolicy =
+                    new PeerEndpointWithPolicyBuilder().setKey(peerEndpointWithPolicyKey)
+                        .setRuleGroupWithRendererEndpointParticipation(new ArrayList<>(entry.getValue()))
+                        .build();
+            peerEpsWithPolicy.add(peerEndpointWithPolicy);
+        }
+        return peerEpsWithPolicy;
+    }
+
+    private static List<PeerExternalEndpointWithPolicy> toListPeerExternalEndpointWithPolicy(
+            Map<PeerExternalEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByPeerExtEp) {
+        List<PeerExternalEndpointWithPolicy> peerExtEpsWithPolicy = new ArrayList<>();
+        for (Entry<PeerExternalEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> entry : policiesByPeerExtEp
+            .entrySet()) {
+            PeerExternalEndpointKey peerEpKey = entry.getKey();
+            PeerExternalEndpointWithPolicyKey peerExternalEpWithPolicyKey =
+                    new PeerExternalEndpointWithPolicyKey(peerEpKey.getAddress(), peerEpKey.getAddressType(),
+                            peerEpKey.getContextId(), peerEpKey.getContextType());
+            PeerExternalEndpointWithPolicy peerExternalEpWithPolicy =
+                    new PeerExternalEndpointWithPolicyBuilder().setKey(peerExternalEpWithPolicyKey)
+                        .setRuleGroupWithRendererEndpointParticipation(new ArrayList<>(entry.getValue()))
+                        .build();
+            peerExtEpsWithPolicy.add(peerExternalEpWithPolicy);
+        }
+        return peerExtEpsWithPolicy;
+    }
+
+    private static List<PeerExternalContainmentEndpointWithPolicy> toListPeerExternalContainmentEndpointWithPolicy(
+            Map<PeerExternalContainmentEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByPeerExtContEp) {
+        List<PeerExternalContainmentEndpointWithPolicy> peerExtContEpsWithPolicy = new ArrayList<>();
+        for (Entry<PeerExternalContainmentEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> entry : policiesByPeerExtContEp
+            .entrySet()) {
+            PeerExternalContainmentEndpointKey peerEpKey = entry.getKey();
+            PeerExternalContainmentEndpointWithPolicyKey peerExternalContEpWithPolicyKey =
+                    new PeerExternalContainmentEndpointWithPolicyKey(peerEpKey.getContextId(),
+                            peerEpKey.getContextType());
+            PeerExternalContainmentEndpointWithPolicy peerExternalContEpWithPolicy =
+                    new PeerExternalContainmentEndpointWithPolicyBuilder().setKey(peerExternalContEpWithPolicyKey)
+                        .setRuleGroupWithRendererEndpointParticipation(new ArrayList<>(entry.getValue()))
+                        .build();
+            peerExtContEpsWithPolicy.add(peerExternalContEpWithPolicy);
+        }
+        return peerExtContEpsWithPolicy;
+    }
+
+    public Endpoints buildEndoints(EndpointInfo epInfo, EndpointLocationInfo epLocInfo,
+            Map<InstanceIdentifier<?>, RendererName> rendererByNode) {
+        List<AddressEndpointWithLocation> epsWithLoc =
+                resolveEpsWithLoc(getAddressEndpointKeys(), epInfo, epLocInfo, rendererByNode);
+        List<ContainmentEndpointWithLocation> contEpsWithLoc =
+                resolveContEpsWithLoc(getContainmentEndpointKeys(), epInfo, epLocInfo);
+        return new EndpointsBuilder().setAddressEndpointWithLocation(epsWithLoc)
+            .setContainmentEndpointWithLocation(contEpsWithLoc)
+            .build();
+    }
+
+    private static List<AddressEndpointWithLocation> resolveEpsWithLoc(Set<AddressEndpointKey> epKeys,
+            EndpointInfo epInfo, EndpointLocationInfo epLocInfo,
+            Map<InstanceIdentifier<?>, RendererName> rendererByNode) {
+        List<AddressEndpointWithLocation> result = new ArrayList<>();
+        for (AddressEndpointKey epKey : epKeys) {
+            Optional<AddressEndpoint> potentialEp = epInfo.getEndpoint(epKey);
+            Preconditions.checkArgument(potentialEp.isPresent());
+            Optional<AddressEndpointLocation> potentionalEpLoc = epLocInfo.getAdressEndpointLocation(epKey);
+            Preconditions.checkArgument(potentionalEpLoc.isPresent());
+            RendererName rendererName = resolveRendererName(potentionalEpLoc.get(), rendererByNode);
+            result.add(createEpWithLoc(potentialEp.get(), potentionalEpLoc.get(), rendererName));
+        }
+        return result;
+    }
+
+    private static RendererName resolveRendererName(AddressEndpointLocation epLoc,
+            Map<InstanceIdentifier<?>, RendererName> rendererByNode) {
+        Optional<InstanceIdentifier<?>> potentialAbsNodeLoc = EndpointLocationUtils.resolveAbsoluteNodeLocation(epLoc);
+        if (potentialAbsNodeLoc.isPresent()) {
+            return rendererByNode.get(potentialAbsNodeLoc.get());
+        }
+        return null;
+    }
+
+    private static AddressEndpointWithLocation createEpWithLoc(AddressEndpoint ep, AddressEndpointLocation epLoc,
+            RendererName rendererName) {
+        return new AddressEndpointWithLocationBuilder().setAddress(ep.getAddress())
+            .setAddressType(ep.getAddressType())
+            .setContextId(ep.getContextId())
+            .setContextType(ep.getContextType())
+            .setTenant(ep.getTenant())
+            .setChildEndpoint(ep.getChildEndpoint())
+            .setParentEndpointChoice(ep.getParentEndpointChoice())
+            .setEndpointGroup(ep.getEndpointGroup())
+            .setCondition(ep.getCondition())
+            .setNetworkContainment(ep.getNetworkContainment())
+            .setTimestamp(ep.getTimestamp())
+            .setAbsoluteLocation(epLoc.getAbsoluteLocation())
+            .setRelativeLocations(epLoc.getRelativeLocations())
+            .setRendererName(rendererName)
+            .build();
+    }
+
+    private static List<ContainmentEndpointWithLocation> resolveContEpsWithLoc(Set<ContainmentEndpointKey> contEpKeys,
+            EndpointInfo epInfo, EndpointLocationInfo epLocInfo) {
+        List<ContainmentEndpointWithLocation> result = new ArrayList<>();
+        for (ContainmentEndpointKey contEpKey : contEpKeys) {
+            Optional<ContainmentEndpoint> potentialContEp = epInfo.getContainmentEndpoint(contEpKey);
+            Preconditions.checkArgument(potentialContEp.isPresent());
+            Optional<ContainmentEndpointLocation> potentialContEpLoc =
+                    epLocInfo.getContainmentEndpointLocation(contEpKey);
+            Preconditions.checkArgument(potentialContEpLoc.isPresent());
+            result.add(createContEpWithLoc(potentialContEp.get(), potentialContEpLoc.get()));
+        }
+        return result;
+    }
+
+    private static ContainmentEndpointWithLocation createContEpWithLoc(ContainmentEndpoint contEp,
+            ContainmentEndpointLocation contEpLoc) {
+        return new ContainmentEndpointWithLocationBuilder().setContextId(contEp.getContextId())
+            .setContextType(contEp.getContextType())
+            .setTenant(contEp.getTenant())
+            .setChildEndpoint(contEp.getChildEndpoint())
+            .setEndpointGroup(contEp.getEndpointGroup())
+            .setCondition(contEp.getCondition())
+            .setNetworkContainment(contEp.getNetworkContainment())
+            .setTimestamp(contEp.getTimestamp())
+            .setRelativeLocations(contEpLoc.getRelativeLocations())
+            .build();
+    }
+
+    public RuleGroups buildRuluGroups(ResolvedPolicyInfo policyInfo) {
+        List<RuleGroup> ruleGroups = resolveRuleGroups(getPolicyRuleGroupKeys(), policyInfo);
+        return new RuleGroupsBuilder().setRuleGroup(ruleGroups).build();
+    }
+
+    private List<RuleGroup> resolveRuleGroups(Set<PolicyRuleGroupKey> policyRuleGrpKeys,
+            ResolvedPolicyInfo policyInfo) {
+        List<RuleGroup> result = new ArrayList<>();
+        for (PolicyRuleGroupKey policyRuleGrpKey : policyRuleGrpKeys) {
+            Optional<PolicyRuleGroup> potentialPolicyRuleGrp = policyInfo.getPolicyRuleGroup(policyRuleGrpKey);
+            Preconditions.checkArgument(potentialPolicyRuleGrp.isPresent());
+            result.add(createRuleGroup(potentialPolicyRuleGrp.get()));
+        }
+        return result;
+    }
+
+    private RuleGroup createRuleGroup(PolicyRuleGroup policyRuleGrp) {
+        return new RuleGroupBuilder().setTenantId(policyRuleGrp.getTenantId())
+            .setContractId(policyRuleGrp.getContractId())
+            .setSubjectName(policyRuleGrp.getSubjectName())
+            .setResolvedRule(policyRuleGrp.getResolvedRule())
+            .setOrder(policyRuleGrp.getOrder())
+            .build();
+    }
+
+    // TODO this copies entire Forwarding to ForwardingContexts - it could copy only forwarding used
+    // in EPs (renderer EPs + peers)
+    public ForwardingContexts buildForwardingContexts(Forwarding forwarding) {
+        List<ForwardingContextByTenant> forwardingContextByTenant =
+                resolveForwardingContextByTenant(forwarding.getForwardingByTenant());
+        return new ForwardingContextsBuilder().setForwardingContextByTenant(forwardingContextByTenant).build();
+    }
+
+    private static List<ForwardingContextByTenant> resolveForwardingContextByTenant(
+            List<ForwardingByTenant> forwardingByTenant) {
+        List<ForwardingContextByTenant> result = new ArrayList<>();
+        for (ForwardingByTenant fwdByTenant : forwardingByTenant) {
+            result.add(new ForwardingContextByTenantBuilder(fwdByTenant).build());
+        }
+        return result;
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java
new file mode 100644 (file)
index 0000000..becf45e
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * 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.renderer;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointLocationsListener;
+import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointsListener;
+import org.opendaylight.groupbasedpolicy.renderer.listener.ForwardingListener;
+import org.opendaylight.groupbasedpolicy.renderer.listener.RenderersListener;
+import org.opendaylight.groupbasedpolicy.renderer.listener.ResolvedPoliciesListener;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+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.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.endpoints.containment.endpoints.ContainmentEndpointKey;
+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.forwarding.rev160427.Forwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RenderersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.containment.endpoints.PeerExternalContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.endpoints.PeerExternalEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.ConfigurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Status;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.ForwardingContexts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+public class RendererManager implements AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RendererManager.class);
+
+    private static long version = 0;
+
+    private final DataBroker dataProvider;
+    private final Set<RendererName> processingRenderers = new HashSet<>();
+    private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
+    private ResolvedPolicyInfo policyInfo;
+    private EndpointInfo epInfo;
+    private EndpointLocationInfo epLocInfo;
+    private Forwarding forwarding;
+
+    private final EndpointsListener endpointsListener;
+    private final EndpointLocationsListener endpointLocationsListener;
+    private final ResolvedPoliciesListener resolvedPoliciesListener;
+    private final ForwardingListener forwardingListener;
+    private final RenderersListener renderersListener;
+
+    public RendererManager(DataBroker dataProvider) {
+        this.dataProvider = checkNotNull(dataProvider);
+        endpointsListener = new EndpointsListener(this, dataProvider);
+        endpointLocationsListener = new EndpointLocationsListener(this, dataProvider);
+        resolvedPoliciesListener = new ResolvedPoliciesListener(this, dataProvider);
+        forwardingListener = new ForwardingListener(this, dataProvider);
+        renderersListener = new RenderersListener(this, dataProvider);
+    }
+
+    public synchronized void endpointsUpdated(final Endpoints endpoints) {
+        epInfo = new EndpointInfo(endpoints);
+        processState();
+    }
+
+    public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
+        epLocInfo = new EndpointLocationInfo(epLocations);
+        processState();
+    }
+
+    public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
+        policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
+        processState();
+    }
+
+    public synchronized void forwardingUpdated(final Forwarding forwarding) {
+        this.forwarding = forwarding;
+        processState();
+    }
+
+    public synchronized void renderersUpdated(final Renderers renderersCont) {
+        ImmutableMultimap<InstanceIdentifier<?>, RendererName> renderersByNode =
+                RendererUtils.resolveRenderersByNodes(renderersCont.getRenderer());
+        rendererByNode = new HashMap<>();
+        for (InstanceIdentifier<?> nodePath : renderersByNode.keySet()) {
+            ImmutableCollection<RendererName> renderers = renderersByNode.get(nodePath);
+            // only first renderer is used
+            rendererByNode.put(nodePath, renderers.asList().get(0));
+        }
+        if (processingRenderers.isEmpty()) {
+            processState();
+        } else {
+            LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
+                    processingRenderers);
+            ImmutableMap<RendererName, Renderer> rendererByName =
+                    RendererUtils.resolveRendererByName(renderersCont.getRenderer());
+            for (RendererName configuredRenderer : processingRenderers) {
+                Renderer renderer = rendererByName.get(configuredRenderer);
+                RendererPolicy rendererPolicy = renderer.getRendererPolicy();
+                if (rendererPolicy != null && rendererPolicy.getVersion() != null
+                        && renderer.getRendererPolicy().getVersion().equals(version)) {
+                    processingRenderers.remove(configuredRenderer);
+                    Status status = rendererPolicy.getStatus();
+                    if (status != null && status.getUnconfiguredRule() != null) {
+                        LOG.warn("Renderer {} did not configure policy with version {} successfully. \n{}",
+                                configuredRenderer.getValue(), version, status);
+                    } else {
+                        LOG.debug("Renderer {} configured policy with version {} successfully.",
+                                configuredRenderer.getValue(), version);
+                    }
+                }
+            }
+        }
+    }
+
+    private void processState() {
+        if (!processingRenderers.isEmpty()) {
+            LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
+                    processingRenderers);
+            return;
+        }
+        if (rendererByNode.values().isEmpty()) {
+            return;
+        }
+
+        version++;
+        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = createRendererConfigBuilders();
+        List<Renderer> renderers = new ArrayList<>();
+        Set<RendererName> rendererNames = new HashSet<>(rendererByNode.values());
+        for (RendererName rendererName : rendererNames) {
+            RendererConfigurationBuilder rendererPolicyBuilder = rendererConfigBuilderByRendererName.get(rendererName);
+            Optional<Configuration> potentialConfig = createConfiguration(rendererPolicyBuilder);
+            RendererPolicy rendererPolicy = null;
+            if (potentialConfig.isPresent()) {
+                LOG.debug("Created configuration for renderer with version {}", rendererName.getValue(), version);
+                rendererPolicy =
+                        new RendererPolicyBuilder().setVersion(version).setConfiguration(potentialConfig.get()).build();
+            } else {
+                rendererPolicy =
+                        new RendererPolicyBuilder().setVersion(version).build();
+            }
+            renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
+            processingRenderers.add(rendererName);
+        }
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Renderers.class),
+                new RenderersBuilder().setRenderer(renderers).build());
+        if (!DataStoreHelper.submitToDs(wTx)) {
+            LOG.warn("Version {} was not dispatched successfully. Previous version is valid till next update.",
+                    version);
+            for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
+                processingRenderers.remove(rendererName);
+            }
+            version--;
+        }
+    }
+
+    /**
+     * Entry is added to the result map only if:<br>
+     * 1. There is at least one Address EP with absolute location
+     * 2. There is a renderer responsible for that EP
+     * 
+     * @return
+     */
+    private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
+        if (!isStateValid()) {
+            return Collections.emptyMap();
+        }
+        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = new HashMap<>();
+        for (InstanceIdentifier<?> absEpLocation : epLocInfo.getAllAbsoluteNodeLocations()) {
+            RendererName rendererName = rendererByNode.get(absEpLocation);
+            if (rendererName == null) {
+                LOG.trace("Renderer does not exist for EP with location: {}", absEpLocation);
+                continue;
+            }
+            RendererConfigurationBuilder rendererConfigBuilder = rendererConfigBuilderByRendererName.get(rendererName);
+            if (rendererConfigBuilder == null) {
+                rendererConfigBuilder = new RendererConfigurationBuilder();
+                rendererConfigBuilderByRendererName.put(rendererName, rendererConfigBuilder);
+            }
+            for (AddressEndpointKey rendererAdrEpKey : epLocInfo.getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
+                Optional<AddressEndpoint> potentialAddressEp = epInfo.getEndpoint(rendererAdrEpKey);
+                if (!potentialAddressEp.isPresent()) {
+                    LOG.trace("Endpoint does not exist but has location: {}", rendererAdrEpKey);
+                    continue;
+                }
+                AddressEndpoint rendererAdrEp = potentialAddressEp.get();
+                resolveRendererConfigForEndpoint(rendererAdrEp, rendererConfigBuilder);
+            }
+        }
+        return rendererConfigBuilderByRendererName;
+    }
+
+    private boolean isStateValid() {
+        if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
+                || forwarding == null) {
+            return false;
+        }
+        return true;
+    }
+
+    private Optional<Configuration> createConfiguration(@Nullable RendererConfigurationBuilder rendererPolicyBuilder) {
+        if (rendererPolicyBuilder == null) {
+            return Optional.absent();
+        }
+        ConfigurationBuilder configBuilder = new ConfigurationBuilder();
+        RendererEndpoints rendererEndpoints = rendererPolicyBuilder.buildRendererEndpoints();
+        if (isRendererEndpointsEmpty(rendererEndpoints)) {
+            return Optional.absent();
+        }
+        configBuilder.setRendererEndpoints(rendererEndpoints);
+
+        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints endpoints =
+                rendererPolicyBuilder.buildEndoints(epInfo, epLocInfo, rendererByNode);
+        configBuilder.setEndpoints(endpoints);
+
+        RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(policyInfo);
+        configBuilder.setRuleGroups(ruleGroups);
+
+        ForwardingContexts forwardingContexts = rendererPolicyBuilder.buildForwardingContexts(forwarding);
+        configBuilder.setForwardingContexts(forwardingContexts);
+
+        return Optional.of(configBuilder.build());
+    }
+
+    private boolean isRendererEndpointsEmpty(RendererEndpoints rendererEndpoints) {
+        if (rendererEndpoints == null || rendererEndpoints.getRendererEndpoint() == null
+                || rendererEndpoints.getRendererEndpoint().isEmpty()) {
+            return true;
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    void resolveRendererConfigForEndpoint(AddressEndpoint rendererAdrEp,
+            RendererConfigurationBuilder rendererPolicyBuilder) {
+        Set<EpgKeyDto> rendererEpgs = toEpgKeys(rendererAdrEp.getEndpointGroup(), rendererAdrEp.getTenant());
+        RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(rendererAdrEp.getKey());
+        for (EpgKeyDto rendererEpg : rendererEpgs) {
+            ImmutableSet<ConsEpgKey> consPeerEpgs = policyInfo.findConsumerPeers(rendererEpg);
+            for (ConsEpgKey consPeerEpg : consPeerEpgs) {
+                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(consPeerEpg, rendererEpg);
+                ResolvedPolicy policy = potentialPolicy.get();
+                ImmutableSet<AddressEndpointKey> consPeerAdrEps = epInfo.findAddressEpsWithEpg(consPeerEpg);
+                resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, consPeerAdrEps, policy,
+                        EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
+                ImmutableSet<ContainmentEndpointKey> consPeerContEps = epInfo.findContainmentEpsWithEpg(consPeerEpg);
+                resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, consPeerContEps, policy,
+                        EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
+            }
+            ImmutableSet<ProvEpgKey> provPeerEpgs = policyInfo.findProviderPeers(rendererEpg);
+            for (ProvEpgKey provPeerEpg : provPeerEpgs) {
+                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(rendererEpg, provPeerEpg);
+                ResolvedPolicy policy = potentialPolicy.get();
+                ImmutableSet<AddressEndpointKey> provPeerAdrEps = epInfo.findAddressEpsWithEpg(provPeerEpg);
+                resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, provPeerAdrEps, policy,
+                        EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
+                ImmutableSet<ContainmentEndpointKey> provPeerContEps = epInfo.findContainmentEpsWithEpg(provPeerEpg);
+                resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, provPeerContEps, policy,
+                        EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
+            }
+        }
+    }
+
+    private void resolveRendererPolicyBetweenEpAndContPeers(RendererEndpointKey rendererEpKey,
+            Set<ContainmentEndpointKey> peerContEps, ResolvedPolicy policy,
+            EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
+        if (isRendererEpInEig(policy, rendererEpParticipation)) {
+            LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
+            LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
+            return;
+        }
+        for (ContainmentEndpointKey peerContEpKey : peerContEps) {
+            ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
+            if (eig != null) { // peers are in EIG
+                if (!epLocInfo.hasRelativeLocation(peerContEpKey)) {
+                    LOG.debug("EIG Containment Peer does not have relative location therefore it is ignored: {}",
+                            peerContEpKey);
+                    continue;
+                }
+                PeerExternalContainmentEndpointKey peerExtContEpKey =
+                        ContainmentEndpointUtils.toPeerExtContEpKey(peerContEpKey);
+                for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
+                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                    // TODO filter based on endpoint constraints
+                    for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
+                        rendererPolicyBuilder.add(rendererEpKey, peerExtContEpKey, ruleGrp.getKey(),
+                                rendererEpParticipation);
+                    }
+                }
+            } else {
+                LOG.info("Peer Containment EP cannot be in other EPG than EIG therefore it is ignored: {}",
+                        peerContEpKey);
+            }
+        }
+    }
+
+    private void resolveRendererPolicyBetweenEpAndPeers(RendererEndpointKey rendererEpKey,
+            Set<AddressEndpointKey> peerAdrEps, ResolvedPolicy policy,
+            EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
+        if (isRendererEpInEig(policy, rendererEpParticipation)) {
+            LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
+            LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
+            return;
+        }
+        for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
+            ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
+            if (eig != null) {
+                if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
+                    LOG.debug("EIG Peer does not have relative location therefore it is ignored: {}", peerAdrEpKey);
+                    continue;
+                }
+                PeerExternalEndpointKey peerExtEpKey = AddressEndpointUtils.toPeerExtEpKey(peerAdrEpKey);
+                for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
+                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                    // TODO filter based on endpoint constraints
+                    for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
+                        rendererPolicyBuilder.add(rendererEpKey, peerExtEpKey, ruleGrp.getKey(),
+                                rendererEpParticipation);
+                    }
+                }
+            } else {
+                if (!epLocInfo.hasRealLocation(peerAdrEpKey)) {
+                    LOG.debug("Peer does not have real location therefore it is ignored: {}", peerAdrEpKey);
+                    continue;
+                }
+                PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(peerAdrEpKey);
+                for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
+                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                    // TODO filter based on endpoint constraints
+                    for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
+                        rendererPolicyBuilder.add(rendererEpKey, peerEpKey, ruleGrp.getKey(), rendererEpParticipation);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isRendererEpInEig(ResolvedPolicy policy, EndpointPolicyParticipation rendererEpParticipation) {
+        ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
+        if (rendererEpParticipation == EndpointPolicyParticipation.PROVIDER
+                && ExternalImplicitGroup.ProviderEpg == eig) {
+            return true;
+        } else if (rendererEpParticipation == EndpointPolicyParticipation.CONSUMER
+                && ExternalImplicitGroup.ConsumerEpg == eig) {
+            return true;
+        }
+        return false;
+    }
+
+    private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
+        return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
+
+            @Override
+            public EpgKeyDto apply(EndpointGroupId input) {
+                return new EpgKeyDto(input, tenantId);
+            }
+        }).toSet();
+    }
+
+    @VisibleForTesting
+    Set<RendererName> getProcessingRenderers() {
+        return processingRenderers;
+    }
+
+    @VisibleForTesting
+    static void resetVersion() {
+        version = 0;
+    }
+
+    @Override
+    public void close() throws Exception {
+        endpointsListener.close();
+        endpointLocationsListener.close();
+        resolvedPoliciesListener.close();
+        forwardingListener.close();
+        renderersListener.close();
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java
new file mode 100644 (file)
index 0000000..08cec8c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+import com.google.common.collect.Maps;
+
+public class RendererUtils {
+
+    public static @Nonnull ImmutableMultimap<InstanceIdentifier<?>, RendererName> resolveRenderersByNodes(
+            @Nullable List<Renderer> renderers) {
+        if (renderers == null) {
+            return ImmutableMultimap.of();
+        }
+        Builder<InstanceIdentifier<?>, RendererName> renderersByNodeBuilder = ImmutableMultimap.builder();
+        for (Renderer renderer : renderers) {
+            List<RendererNode> rendererNodes = renderer.getRendererNodes().getRendererNode();
+            if (rendererNodes == null) {
+                continue;
+            }
+            for (RendererNode rendererNode : rendererNodes) {
+                if (rendererNode.getNodePath() != null) {
+                    renderersByNodeBuilder.put(rendererNode.getNodePath(), renderer.getName());
+                }
+            }
+        }
+        return renderersByNodeBuilder.build();
+    }
+
+    public static @Nonnull ImmutableMap<RendererName, Renderer> resolveRendererByName(
+            @Nullable List<Renderer> renderers) {
+        if (renderers == null) {
+            return ImmutableMap.of();
+        }
+        return Maps.uniqueIndex(renderers, Renderer::getName);
+    }
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ResolvedPolicyInfo.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ResolvedPolicyInfo.java
new file mode 100644 (file)
index 0000000..3bb8b89
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.renderer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupKey;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.ImmutableTable.Builder;
+
+public class ResolvedPolicyInfo {
+
+    private final ImmutableTable<ConsEpgKey, ProvEpgKey, ResolvedPolicy> policyByEpgs;
+    private final Map<PolicyRuleGroupKey, PolicyRuleGroup> policyRuleGrpByKey = new HashMap<>();
+
+    public ResolvedPolicyInfo(ResolvedPolicies resolvedPolicies) {
+        if (resolvedPolicies.getResolvedPolicy() == null) {
+            policyByEpgs = ImmutableTable.of();
+        } else {
+            Builder<ConsEpgKey, ProvEpgKey, ResolvedPolicy> policyByEpgsBuilder = new Builder<>();
+            for (ResolvedPolicy resolvedPolicy : resolvedPolicies.getResolvedPolicy()) {
+                policyByEpgsBuilder.put(
+                        new EpgKeyDto(resolvedPolicy.getConsumerEpgId(), resolvedPolicy.getConsumerTenantId()),
+                        new EpgKeyDto(resolvedPolicy.getProviderEpgId(), resolvedPolicy.getProviderTenantId()),
+                        resolvedPolicy);
+                for (PolicyRuleGroupWithEndpointConstraints ruleGrpWithEpConstraints : resolvedPolicy
+                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                    for (PolicyRuleGroup ruleGrp : ruleGrpWithEpConstraints.getPolicyRuleGroup()) {
+                        policyRuleGrpByKey.put(ruleGrp.getKey(), ruleGrp);
+                    }
+                }
+            }
+            policyByEpgs = policyByEpgsBuilder.build();
+        }
+    }
+
+    public Optional<PolicyRuleGroup> getPolicyRuleGroup(PolicyRuleGroupKey policyRuleGrpKey) {
+        return Optional.fromNullable(policyRuleGrpByKey.get(policyRuleGrpKey));
+    }
+
+    public ImmutableSet<ProvEpgKey> findProviderPeers(ConsEpgKey consKey) {
+        return policyByEpgs.row(consKey).keySet();
+    }
+
+    public ImmutableSet<ConsEpgKey> findConsumerPeers(ProvEpgKey provKey) {
+        return policyByEpgs.column(provKey).keySet();
+    }
+
+    public Optional<ResolvedPolicy> findPolicy(ConsEpgKey consKey, ProvEpgKey provKey) {
+        return Optional.fromNullable(policyByEpgs.get(consKey, provKey));
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointLocationsListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointLocationsListener.java
new file mode 100644 (file)
index 0000000..1a0c05b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.listener;
+
+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.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EndpointLocationsListener extends DataTreeChangeHandler<EndpointLocations> implements AutoCloseable {
+
+    private final RendererManager rendererManager;
+
+    public EndpointLocationsListener(RendererManager rendererManager, DataBroker dataProvider) {
+        super(dataProvider);
+        this.rendererManager = rendererManager;
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.create(EndpointLocations.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<EndpointLocations> rootNode,
+            InstanceIdentifier<EndpointLocations> rootIdentifier) {
+        rendererManager.endpointLocationsUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<EndpointLocations> rootNode,
+            InstanceIdentifier<EndpointLocations> rootIdentifier) {
+        rendererManager.endpointLocationsUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<EndpointLocations> rootNode,
+            InstanceIdentifier<EndpointLocations> rootIdentifier) {
+        rendererManager.endpointLocationsUpdated(rootNode.getDataAfter());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointsListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/EndpointsListener.java
new file mode 100644 (file)
index 0000000..6a642ed
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.renderer.listener;
+
+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.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EndpointsListener extends DataTreeChangeHandler<Endpoints> implements AutoCloseable {
+
+    private final RendererManager rendererManager;
+
+    public EndpointsListener(RendererManager rendererManager, DataBroker dataProvider) {
+        super(dataProvider);
+        this.rendererManager = rendererManager;
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Endpoints.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<Endpoints> rootNode, InstanceIdentifier<Endpoints> rootIdentifier) {
+        rendererManager.endpointsUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<Endpoints> rootNode, InstanceIdentifier<Endpoints> rootIdentifier) {
+        rendererManager.endpointsUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<Endpoints> rootNode,
+            InstanceIdentifier<Endpoints> rootIdentifier) {
+        rendererManager.endpointsUpdated(rootNode.getDataAfter());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ForwardingListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ForwardingListener.java
new file mode 100644 (file)
index 0000000..dbb3101
--- /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.renderer.listener;
+
+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.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ForwardingListener extends DataTreeChangeHandler<Forwarding> implements AutoCloseable {
+
+    private final RendererManager rendererManager;
+
+    public ForwardingListener(RendererManager rendererManager, DataBroker dataProvider) {
+        super(dataProvider);
+        this.rendererManager = rendererManager;
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.create(Forwarding.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<Forwarding> rootNode, InstanceIdentifier<Forwarding> rootIdentifier) {
+        rendererManager.forwardingUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<Forwarding> rootNode,
+            InstanceIdentifier<Forwarding> rootIdentifier) {
+        rendererManager.forwardingUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<Forwarding> rootNode,
+            InstanceIdentifier<Forwarding> rootIdentifier) {
+        rendererManager.forwardingUpdated(rootNode.getDataAfter());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/RenderersListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/RenderersListener.java
new file mode 100644 (file)
index 0000000..0e840b5
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.renderer.listener;
+
+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.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RenderersListener extends DataTreeChangeHandler<Renderers> implements AutoCloseable {
+
+    private final RendererManager rendererManager;
+
+    public RenderersListener(RendererManager rendererManager, DataBroker dataProvider) {
+        super(dataProvider);
+        this.rendererManager = rendererManager;
+        registerDataTreeChangeListener(
+                new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Renderers.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<Renderers> rootNode, InstanceIdentifier<Renderers> rootIdentifier) {
+        rendererManager.renderersUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<Renderers> rootNode, InstanceIdentifier<Renderers> rootIdentifier) {
+        rendererManager.renderersUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<Renderers> rootNode,
+            InstanceIdentifier<Renderers> rootIdentifier) {
+        rendererManager.renderersUpdated(rootNode.getDataAfter());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ResolvedPoliciesListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/listener/ResolvedPoliciesListener.java
new file mode 100644 (file)
index 0000000..f7ed106
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.listener;
+
+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.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.RendererManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ResolvedPoliciesListener extends DataTreeChangeHandler<ResolvedPolicies> implements AutoCloseable {
+
+    private final RendererManager rendererManager;
+
+    public ResolvedPoliciesListener(RendererManager rendererManager, DataBroker dataProvider) {
+        super(dataProvider);
+        this.rendererManager = rendererManager;
+        registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.create(ResolvedPolicies.class)));
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<ResolvedPolicies> rootNode,
+            InstanceIdentifier<ResolvedPolicies> rootIdentifier) {
+        rendererManager.resolvedPoliciesUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<ResolvedPolicies> rootNode,
+            InstanceIdentifier<ResolvedPolicies> rootIdentifier) {
+        rendererManager.resolvedPoliciesUpdated(rootNode.getDataAfter());
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<ResolvedPolicies> rootNode,
+            InstanceIdentifier<ResolvedPolicies> rootIdentifier) {
+        rendererManager.resolvedPoliciesUpdated(rootNode.getDataAfter());
+    }
+
+}
index e5fa0283e1306715107e9228c1968e2bc820b70f..8d052d433eb823a707511809c849e96e24e34962 100755 (executable)
@@ -141,9 +141,6 @@ module renderer {
     }
 
     container renderers {
-        description
-            "Leaf containing all renderers' description.";
-
         list renderer {
             description
                 "A renderer provides a list of capabilities and status about configured policy.
@@ -188,6 +185,7 @@ module renderer {
                     description "Renderer tries to apply given policy on devices.";
                     container renderer-endpoints {
                         list renderer-endpoint {
+                            min-elements 1;
                             description "Policy between renderer-endpoint and peer-endpoints (peers).
                                 Renderer configures policy for renderer endpoints.";
                             key "context-type context-id address-type address";
@@ -215,6 +213,7 @@ module renderer {
 
                     container rule-groups {
                         list rule-group {
+                            min-elements 1;
                             description "A specific policy rule group that apply to pair of endpoints.
                                 The policy rule group represents the subject with resolved rules.";
                             key "tenant-id contract-id subject-name";
@@ -227,6 +226,7 @@ module renderer {
 
                     container endpoints {
                         list address-endpoint-with-location {
+                            min-elements 1;
                             key "context-type context-id address-type address";
                             uses base-endpoint:address-endpoint-fields;
                             uses base-endpoint:has-location;
@@ -242,6 +242,7 @@ module renderer {
 
                     container forwarding-contexts {
                         list forwarding-context-by-tenant {
+                            min-elements 1;
                             key tenant-id;
                             uses forwarding:forwarding-with-tenant-fields;
                         }
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerDataBrokerTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerDataBrokerTest.java
new file mode 100644 (file)
index 0000000..1fde0ca
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * 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.renderer;
+
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+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.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocationsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.ContainmentEndpointsBuilder;
+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.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ForwardingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.with.tenant.fields.ForwardingContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RenderersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.ForwardingContexts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPoliciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.CheckedFuture;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RendererManagerDataBrokerTest {
+
+    private static final RendererName RENDERER_NAME_R1 = new RendererName("R1");
+    private static final EndpointGroupId EPG_BLUE = new EndpointGroupId("blue_epg");
+    private static final EndpointGroupId EPG_PURPLE = new EndpointGroupId("purple_epg");
+    private static final ContractId CONTRACT_1 = new ContractId("contract_1");
+    private static final SubjectName SUBJECT_1 = new SubjectName("subject_1");
+    private static final RuleName RULE_1 = new RuleName("rule_1");
+    private static final String ADR_1 = "adr_1";
+    private static final String ADR_2 = "adr_2";
+    private static final InstanceIdentifier<?> NODE_PATH_1 = InstanceIdentifier.create(Tenants.class);
+    private static final InternalLocationCase INT_LOC_CASE_NODE_PATH_1 =
+            new InternalLocationCaseBuilder().setInternalNode(NODE_PATH_1).build();
+    private static final InternalLocation INT_LOC_NODE_PATH_1 =
+            new InternalLocationBuilder().setInternalNode(NODE_PATH_1).build();
+    private static final ExternalLocationCase EXT_LOC_CASE_NODE_PATH_1 =
+            new ExternalLocationCaseBuilder().setExternalNodeMountPoint(NODE_PATH_1).build();
+
+    @Mock
+    private DataBroker dataProvider;
+    @Mock
+    private WriteTransaction wTx;
+    @Mock
+    private CheckedFuture<Void, TransactionCommitFailedException> submitFuture;
+
+    private RendererManager rendererManager;
+
+    @Before
+    public void init() {
+        Mockito.when(dataProvider.newWriteOnlyTransaction()).thenReturn(wTx);
+        Mockito.when(wTx.submit()).thenReturn(submitFuture);
+        rendererManager = new RendererManager(dataProvider);
+        RendererManager.resetVersion();
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+     */
+    @Test
+    public void testProcessState_dispatchOnePolicy_rendererFeedbackPositive() throws Exception {
+        ArgumentCaptor<Renderers> acRenderers = ArgumentCaptor.forClass(Renderers.class);
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        ResolvedPolicy resolvedPolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1).build();
+        ResolvedPolicies resolvedPolicies =
+                new ResolvedPoliciesBuilder().setResolvedPolicy(ImmutableList.of(resolvedPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE).build();
+        AddressEndpoint ep2 = TestDataFactory.defaultAdrEp(ADR_2, EPG_PURPLE).build();
+        rendererManager.endpointsUpdated(new EndpointsBuilder()
+            .setAddressEndpoints(new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1, ep2)).build())
+            .build());
+
+        AddressEndpointLocation ep1Loc =
+                TestDataFactory.defaultAdrEpLoc(ep1.getKey(), INT_LOC_CASE_NODE_PATH_1).build();
+        AddressEndpointLocation ep2Loc =
+                TestDataFactory.defaultAdrEpLoc(ep2.getKey(), INT_LOC_CASE_NODE_PATH_1).build();
+        EndpointLocations endpointLocations =
+                new EndpointLocationsBuilder().setAddressEndpointLocation(ImmutableList.of(ep1Loc, ep2Loc)).build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        rendererManager
+            .forwardingUpdated(new ForwardingBuilder()
+                .setForwardingByTenant(
+                        Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
+                            .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
+                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextId(TestDataFactory.CTX_1)
+                                .build()))
+                            .build()))
+                .build());
+
+        rendererManager.renderersUpdated(new RenderersBuilder()
+            .setRenderer(Arrays.asList(new RendererBuilder().setName(RENDERER_NAME_R1)
+                .setRendererNodes(new RendererNodesBuilder()
+                    .setRendererNode(Arrays.asList(new RendererNodeBuilder().setNodePath(NODE_PATH_1).build())).build())
+                .build()))
+            .build());
+
+        // assert dispatch one policy
+        Assert.assertEquals(1, rendererManager.getProcessingRenderers().size());
+        Mockito.verify(wTx).put(Mockito.eq(LogicalDatastoreType.CONFIGURATION),
+                Mockito.eq(InstanceIdentifier.create(Renderers.class)),
+                acRenderers.capture());
+
+        Renderers renderers = acRenderers.getValue();
+        Assert.assertNotNull(renderers);
+        Assert.assertNotNull(renderers.getRenderer());
+        Assert.assertEquals(1, renderers.getRenderer().size());
+        Renderer renderer = renderers.getRenderer().get(0);
+        Assert.assertEquals(RENDERER_NAME_R1, renderer.getName());
+        RendererPolicy rendererPolicy = renderer.getRendererPolicy();
+        Assert.assertNotNull(rendererPolicy);
+        Assert.assertEquals(1, rendererPolicy.getVersion().longValue());
+
+        Configuration configuration = rendererPolicy.getConfiguration();
+        Assert.assertNotNull(configuration);
+        RendererEndpoints rendererEndpoints = configuration.getRendererEndpoints();
+        Assert.assertNotNull(rendererEndpoints);
+        Assert.assertEquals(2, rendererEndpoints.getRendererEndpoint().size());
+
+        ForwardingContexts forwardingContexts = configuration.getForwardingContexts();
+        Assert.assertNotNull(forwardingContexts);
+        Assert.assertEquals(1, forwardingContexts.getForwardingContextByTenant().size());
+
+        Endpoints endpoints = configuration.getEndpoints();
+        Assert.assertNotNull(endpoints);
+        Assert.assertEquals(2, endpoints.getAddressEndpointWithLocation().size());
+
+        RuleGroups ruleGroups = configuration.getRuleGroups();
+        Assert.assertNotNull(ruleGroups);
+        Assert.assertEquals(1, ruleGroups.getRuleGroup().size());
+
+        rendererManager
+            .renderersUpdated(
+                    new RenderersBuilder()
+                        .setRenderer(
+                                Arrays.asList(new RendererBuilder().setName(RENDERER_NAME_R1)
+                                    .setRendererNodes(new RendererNodesBuilder()
+                                        .setRendererNode(Arrays
+                                            .asList(new RendererNodeBuilder().setNodePath(NODE_PATH_1).build()))
+                                        .build())
+                                    .setRendererPolicy(new RendererPolicyBuilder().setVersion(1L).build())
+                                    .build()))
+                        .build());
+        Assert.assertEquals(0, rendererManager.getProcessingRenderers().size());
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE(EIG)--EP2(containment)
+     */
+    @Test
+    public void testProcessState_dispatchOneExternalPolicyWithContainmentEp_noRendererFeedback() throws Exception {
+        ArgumentCaptor<Renderers> acRenderers = ArgumentCaptor.forClass(Renderers.class);
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        ResolvedPolicy resolvedPolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1)
+            .setExternalImplicitGroup(ExternalImplicitGroup.ProviderEpg)
+            .build();
+        ResolvedPolicies resolvedPolicies =
+                new ResolvedPoliciesBuilder().setResolvedPolicy(ImmutableList.of(resolvedPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE).build();
+        ContainmentEndpoint ep2 = TestDataFactory.defaultContEp(EPG_PURPLE).build();
+        rendererManager
+            .endpointsUpdated(new EndpointsBuilder()
+                .setAddressEndpoints(new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1)).build())
+                .setContainmentEndpoints(
+                        new ContainmentEndpointsBuilder().setContainmentEndpoint(ImmutableList.of(ep2)).build())
+                .build());
+
+        AddressEndpointLocation ep1Loc =
+                TestDataFactory.defaultAdrEpLoc(ep1.getKey(), INT_LOC_CASE_NODE_PATH_1).build();
+        ContainmentEndpointLocation ep2Loc =
+                TestDataFactory.defaultContEpLoc(ep2.getKey(), INT_LOC_NODE_PATH_1).build();
+        EndpointLocations endpointLocations =
+                new EndpointLocationsBuilder().setAddressEndpointLocation(ImmutableList.of(ep1Loc))
+                    .setContainmentEndpointLocation(ImmutableList.of(ep2Loc))
+                    .build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        rendererManager
+            .forwardingUpdated(new ForwardingBuilder()
+                .setForwardingByTenant(
+                        Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
+                            .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
+                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextId(TestDataFactory.CTX_1)
+                                .build()))
+                            .build()))
+                .build());
+
+        rendererManager.renderersUpdated(new RenderersBuilder()
+            .setRenderer(Arrays.asList(new RendererBuilder().setName(RENDERER_NAME_R1)
+                .setRendererNodes(new RendererNodesBuilder()
+                    .setRendererNode(Arrays.asList(new RendererNodeBuilder().setNodePath(NODE_PATH_1).build())).build())
+                .build()))
+            .build());
+
+        // assert dispatch one policy
+        Assert.assertEquals(1, rendererManager.getProcessingRenderers().size());
+        Mockito.verify(wTx).put(Mockito.eq(LogicalDatastoreType.CONFIGURATION),
+                Mockito.eq(InstanceIdentifier.create(Renderers.class)),
+                acRenderers.capture());
+
+        Renderers renderers = acRenderers.getValue();
+        Assert.assertNotNull(renderers);
+        Assert.assertNotNull(renderers.getRenderer());
+        Assert.assertEquals(1, renderers.getRenderer().size());
+        Renderer renderer = renderers.getRenderer().get(0);
+        Assert.assertEquals(RENDERER_NAME_R1, renderer.getName());
+        RendererPolicy rendererPolicy = renderer.getRendererPolicy();
+        Assert.assertNotNull(rendererPolicy);
+        Assert.assertEquals(1, rendererPolicy.getVersion().longValue());
+
+        Configuration configuration = rendererPolicy.getConfiguration();
+        Assert.assertNotNull(configuration);
+        RendererEndpoints rendererEndpoints = configuration.getRendererEndpoints();
+        Assert.assertNotNull(rendererEndpoints);
+        Assert.assertEquals(1, rendererEndpoints.getRendererEndpoint().size());
+
+        ForwardingContexts forwardingContexts = configuration.getForwardingContexts();
+        Assert.assertNotNull(forwardingContexts);
+        Assert.assertEquals(1, forwardingContexts.getForwardingContextByTenant().size());
+
+        Endpoints endpoints = configuration.getEndpoints();
+        Assert.assertNotNull(endpoints);
+        Assert.assertEquals(1, endpoints.getAddressEndpointWithLocation().size());
+        Assert.assertEquals(1, endpoints.getContainmentEndpointWithLocation().size());
+
+        RuleGroups ruleGroups = configuration.getRuleGroups();
+        Assert.assertNotNull(ruleGroups);
+        Assert.assertEquals(1, ruleGroups.getRuleGroup().size());
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE(EIG)--EP2()
+     */
+    @Test
+    public void testProcessState_dispatchOneExternalPolicyWithEp_noRendererFeedback() {
+        ArgumentCaptor<Renderers> acRenderers = ArgumentCaptor.forClass(Renderers.class);
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        ResolvedPolicy resolvedPolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1)
+            .setExternalImplicitGroup(ExternalImplicitGroup.ProviderEpg)
+            .build();
+        ResolvedPolicies resolvedPolicies =
+                new ResolvedPoliciesBuilder().setResolvedPolicy(ImmutableList.of(resolvedPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE).build();
+        AddressEndpoint ep2 = TestDataFactory.defaultAdrEp(ADR_2, EPG_PURPLE).build();
+        rendererManager.endpointsUpdated(new EndpointsBuilder()
+            .setAddressEndpoints(new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1, ep2)).build())
+            .build());
+
+        AddressEndpointLocation ep1Loc =
+                TestDataFactory.defaultAdrEpLoc(ep1.getKey(), INT_LOC_CASE_NODE_PATH_1).build();
+        AddressEndpointLocation ep2Loc =
+                TestDataFactory.defaultAdrEpLoc(ep2.getKey(), EXT_LOC_CASE_NODE_PATH_1).build();
+        EndpointLocations endpointLocations =
+                new EndpointLocationsBuilder().setAddressEndpointLocation(ImmutableList.of(ep1Loc, ep2Loc)).build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        rendererManager
+            .forwardingUpdated(new ForwardingBuilder()
+                .setForwardingByTenant(
+                        Arrays.asList(new ForwardingByTenantBuilder().setTenantId(TestDataFactory.TENANT_ID)
+                            .setForwardingContext(Arrays.asList(new ForwardingContextBuilder()
+                                .setContextType(TestDataFactory.DummyContextType.class)
+                                .setContextId(TestDataFactory.CTX_1)
+                                .build()))
+                            .build()))
+                .build());
+
+        rendererManager.renderersUpdated(new RenderersBuilder()
+            .setRenderer(Arrays.asList(new RendererBuilder().setName(RENDERER_NAME_R1)
+                .setRendererNodes(new RendererNodesBuilder()
+                    .setRendererNode(Arrays.asList(new RendererNodeBuilder().setNodePath(NODE_PATH_1).build())).build())
+                .build()))
+            .build());
+
+        // assert dispatch one policy
+        Assert.assertEquals(1, rendererManager.getProcessingRenderers().size());
+        Mockito.verify(wTx).put(Mockito.eq(LogicalDatastoreType.CONFIGURATION),
+                Mockito.eq(InstanceIdentifier.create(Renderers.class)),
+                acRenderers.capture());
+
+        Renderers renderers = acRenderers.getValue();
+        Assert.assertNotNull(renderers);
+        Assert.assertNotNull(renderers.getRenderer());
+        Assert.assertEquals(1, renderers.getRenderer().size());
+        Renderer renderer = renderers.getRenderer().get(0);
+        Assert.assertEquals(RENDERER_NAME_R1, renderer.getName());
+        RendererPolicy rendererPolicy = renderer.getRendererPolicy();
+        Assert.assertNotNull(rendererPolicy);
+        Assert.assertEquals(1, rendererPolicy.getVersion().longValue());
+
+        Configuration configuration = rendererPolicy.getConfiguration();
+        Assert.assertNotNull(configuration);
+        RendererEndpoints rendererEndpoints = configuration.getRendererEndpoints();
+        Assert.assertNotNull(rendererEndpoints);
+        Assert.assertEquals(1, rendererEndpoints.getRendererEndpoint().size());
+
+        ForwardingContexts forwardingContexts = configuration.getForwardingContexts();
+        Assert.assertNotNull(forwardingContexts);
+        Assert.assertEquals(1, forwardingContexts.getForwardingContextByTenant().size());
+
+        Endpoints endpoints = configuration.getEndpoints();
+        Assert.assertNotNull(endpoints);
+        Assert.assertEquals(2, endpoints.getAddressEndpointWithLocation().size());
+
+        RuleGroups ruleGroups = configuration.getRuleGroups();
+        Assert.assertNotNull(ruleGroups);
+        Assert.assertEquals(1, ruleGroups.getRuleGroup().size());
+    }
+
+}
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/RendererManagerTest.java
new file mode 100644 (file)
index 0000000..6c792d8
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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.renderer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocationsBuilder;
+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.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpointsBuilder;
+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.has.absolute.location.absolute.location.location.type.InternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPoliciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableTable;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RendererManagerTest {
+
+    private static final EndpointGroupId EPG_BLUE = new EndpointGroupId("blue_epg");
+    private static final EndpointGroupId EPG_PURPLE = new EndpointGroupId("purple_epg");
+    private static final EndpointGroupId EPG_RED = new EndpointGroupId("red_epg");
+    private static final EndpointGroupId EPG_GREY = new EndpointGroupId("grey_epg");
+    private static final ContractId CONTRACT_1 = new ContractId("contract_1");
+    private static final SubjectName SUBJECT_1 = new SubjectName("subject_1");
+    private static final RuleName RULE_1 = new RuleName("rule_1");
+    private static final ContractId CONTRACT_2 = new ContractId("contract_2");
+    private static final SubjectName SUBJECT_2 = new SubjectName("subject_2");
+    private static final String ADR_1 = "adr_1";
+    private static final String ADR_2 = "adr_2";
+    private static final String ADR_3 = "adr_3";
+    private static final String ADR_4 = "adr_4";
+    private static final InstanceIdentifier<?> NODE_PATH_1 = InstanceIdentifier.create(Tenants.class);
+    private static final InternalLocationCase REG_LOC_NODE_PATH_1 =
+            new InternalLocationCaseBuilder().setInternalNode(NODE_PATH_1).build();
+
+    @Mock
+    private DataBroker dataProvider;
+
+    private RendererManager rendererManager;
+
+    @Before
+    public void init() {
+        rendererManager = new RendererManager(dataProvider);
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+     */
+    @Test
+    public void testResolveRendererPolicyForEndpoint_onePolicy() {
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        ResolvedPolicy resolvedPolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1).build();
+        ResolvedPolicies resolvedPolicies =
+                new ResolvedPoliciesBuilder().setResolvedPolicy(ImmutableList.of(resolvedPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE).build();
+        AddressEndpoint ep2 = TestDataFactory.defaultAdrEp(ADR_2, EPG_PURPLE).build();
+        Endpoints endpoints = new EndpointsBuilder()
+            .setAddressEndpoints(new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1, ep2)).build())
+            .build();
+        rendererManager.endpointsUpdated(endpoints);
+
+        AddressEndpointLocation ep1Loc = TestDataFactory.defaultAdrEpLoc(ep1.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep2Loc = TestDataFactory.defaultAdrEpLoc(ep2.getKey(), REG_LOC_NODE_PATH_1).build();
+        EndpointLocations endpointLocations =
+                new EndpointLocationsBuilder().setAddressEndpointLocation(ImmutableList.of(ep1Loc, ep2Loc)).build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        RendererConfigurationBuilder rendererPolicyBuilder = new RendererConfigurationBuilder();
+        rendererManager.resolveRendererConfigForEndpoint(ep1, rendererPolicyBuilder);
+        ImmutableTable<RendererEndpointKey, PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerEp =
+                rendererPolicyBuilder.getPoliciesByEpAndPeerEp();
+        assertFalse(policiesByEpAndPeerEp.isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtEp().isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtConEp().isEmpty());
+        assertEquals(1, policiesByEpAndPeerEp.rowKeySet().size());
+        assertEquals(1, policiesByEpAndPeerEp.columnKeySet().size());
+        // check EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+        RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(ep1.getKey());
+        assertEquals(rendererEpKey, policiesByEpAndPeerEp.rowKeySet().iterator().next());
+        PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(ep2.getKey());
+        assertEquals(peerEpKey, policiesByEpAndPeerEp.columnKeySet().iterator().next());
+        Set<RuleGroupWithRendererEndpointParticipation> ruleGrpsWithEpPartic =
+                policiesByEpAndPeerEp.get(rendererEpKey, peerEpKey);
+        assertEquals(1, ruleGrpsWithEpPartic.size());
+        RuleGroupWithRendererEndpointParticipation ruleGrpWithEpPartic = ruleGrpsWithEpPartic.iterator().next();
+        assertEquals(ruleGrp1.getTenantId(), ruleGrpWithEpPartic.getTenantId());
+        assertEquals(ruleGrp1.getContractId(), ruleGrpWithEpPartic.getContractId());
+        assertEquals(ruleGrp1.getSubjectName(), ruleGrpWithEpPartic.getSubjectName());
+        assertEquals(EndpointPolicyParticipation.CONSUMER, ruleGrpWithEpPartic.getRendererEndpointParticipation());
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+     * <br>
+     * EP3--EPG_RED----SUBJECT_1---(P)EPG_GREY--EP4
+     */
+    @Test
+    public void testResolveRendererPolicyForEndpoint_onePolicyTwoUsage() {
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        ResolvedPolicy bluePurplePolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1).build();
+        ResolvedPolicy redGreyPolicy = TestDataFactory.defaultResolvedPolicy(EPG_RED, EPG_GREY, ruleGrp1).build();
+        ResolvedPolicies resolvedPolicies = new ResolvedPoliciesBuilder()
+            .setResolvedPolicy(ImmutableList.of(bluePurplePolicy, redGreyPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE).build();
+        AddressEndpoint ep2 = TestDataFactory.defaultAdrEp(ADR_2, EPG_PURPLE).build();
+        AddressEndpoint ep3 = TestDataFactory.defaultAdrEp(ADR_3, EPG_RED).build();
+        AddressEndpoint ep4 = TestDataFactory.defaultAdrEp(ADR_4, EPG_GREY).build();
+        Endpoints endpoints = new EndpointsBuilder()
+            .setAddressEndpoints(
+                    new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1, ep2, ep3, ep4)).build())
+            .build();
+        rendererManager.endpointsUpdated(endpoints);
+
+        AddressEndpointLocation ep1Loc = TestDataFactory.defaultAdrEpLoc(ep1.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep2Loc = TestDataFactory.defaultAdrEpLoc(ep2.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep3Loc = TestDataFactory.defaultAdrEpLoc(ep3.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep4Loc = TestDataFactory.defaultAdrEpLoc(ep4.getKey(), REG_LOC_NODE_PATH_1).build();
+        EndpointLocations endpointLocations = new EndpointLocationsBuilder()
+            .setAddressEndpointLocation(ImmutableList.of(ep1Loc, ep2Loc, ep3Loc, ep4Loc)).build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        // EP1, EP3 as renderer endpoints
+        RendererConfigurationBuilder rendererPolicyBuilder = new RendererConfigurationBuilder();
+        rendererManager.resolveRendererConfigForEndpoint(ep1, rendererPolicyBuilder);
+        rendererManager.resolveRendererConfigForEndpoint(ep3, rendererPolicyBuilder);
+        ImmutableTable<RendererEndpointKey, PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerEp =
+                rendererPolicyBuilder.getPoliciesByEpAndPeerEp();
+        assertFalse(policiesByEpAndPeerEp.isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtEp().isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtConEp().isEmpty());
+        assertEquals(2, policiesByEpAndPeerEp.rowKeySet().size());
+        assertEquals(2, policiesByEpAndPeerEp.columnKeySet().size());
+        // check EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE
+        RendererEndpointKey ep1RendererEpKey = AddressEndpointUtils.toRendererEpKey(ep1.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsRow(ep1RendererEpKey));
+        PeerEndpointKey ep2PeerEpKey = AddressEndpointUtils.toPeerEpKey(ep2.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsColumn(ep2PeerEpKey));
+        Set<RuleGroupWithRendererEndpointParticipation> ep1Ep2RuleGrpsWithEpPartic =
+                policiesByEpAndPeerEp.get(ep1RendererEpKey, ep2PeerEpKey);
+        assertEquals(1, ep1Ep2RuleGrpsWithEpPartic.size());
+        RuleGroupWithRendererEndpointParticipation ruleGrp1WithEpPartic = ep1Ep2RuleGrpsWithEpPartic.iterator().next();
+        assertEquals(ruleGrp1.getTenantId(), ruleGrp1WithEpPartic.getTenantId());
+        assertEquals(ruleGrp1.getContractId(), ruleGrp1WithEpPartic.getContractId());
+        assertEquals(ruleGrp1.getSubjectName(), ruleGrp1WithEpPartic.getSubjectName());
+        assertEquals(EndpointPolicyParticipation.CONSUMER, ruleGrp1WithEpPartic.getRendererEndpointParticipation());
+        // check EP3--EPG_RED----SUBJECT_1---(P)EPG_GREY--EP4
+        RendererEndpointKey ep3RendererEpKey = AddressEndpointUtils.toRendererEpKey(ep3.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsRow(ep3RendererEpKey));
+        PeerEndpointKey ep4PeerEpKey = AddressEndpointUtils.toPeerEpKey(ep4.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsColumn(ep4PeerEpKey));
+        Set<RuleGroupWithRendererEndpointParticipation> ep3Ep4RuleGrpsWithEpPartic =
+                policiesByEpAndPeerEp.get(ep3RendererEpKey, ep4PeerEpKey);
+        assertEquals(1, ep3Ep4RuleGrpsWithEpPartic.size());
+        ruleGrp1WithEpPartic = ep3Ep4RuleGrpsWithEpPartic.iterator().next();
+        assertEquals(ruleGrp1.getTenantId(), ruleGrp1WithEpPartic.getTenantId());
+        assertEquals(ruleGrp1.getContractId(), ruleGrp1WithEpPartic.getContractId());
+        assertEquals(ruleGrp1.getSubjectName(), ruleGrp1WithEpPartic.getSubjectName());
+        assertEquals(EndpointPolicyParticipation.CONSUMER, ruleGrp1WithEpPartic.getRendererEndpointParticipation());
+    }
+
+    /**
+     * EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+     * <br>
+     * EP1--EPG_RED----SUBJECT_2---(P)EPG_GREY--EP2,EP3
+     */
+    @Test
+    public void testResolveRendererPolicyForEndpoint_twoPolicy() {
+        ResolvedRule rule1 = TestDataFactory.defaultResolvedRule(RULE_1).build();
+        PolicyRuleGroup ruleGrp1 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_1, SUBJECT_1, rule1).build();
+        PolicyRuleGroup ruleGrp2 = TestDataFactory.defaultPolicyRuleGrp(CONTRACT_2, SUBJECT_2, rule1).build();
+        ResolvedPolicy bluePurplePolicy = TestDataFactory.defaultResolvedPolicy(EPG_BLUE, EPG_PURPLE, ruleGrp1).build();
+        ResolvedPolicy redGreyPolicy = TestDataFactory.defaultResolvedPolicy(EPG_RED, EPG_GREY, ruleGrp2).build();
+        ResolvedPolicies resolvedPolicies = new ResolvedPoliciesBuilder()
+            .setResolvedPolicy(ImmutableList.of(bluePurplePolicy, redGreyPolicy)).build();
+        rendererManager.resolvedPoliciesUpdated(resolvedPolicies);
+
+        AddressEndpoint ep1 = TestDataFactory.defaultAdrEp(ADR_1, EPG_BLUE, EPG_RED).build();
+        AddressEndpoint ep2 = TestDataFactory.defaultAdrEp(ADR_2, EPG_PURPLE, EPG_GREY).build();
+        AddressEndpoint ep3 = TestDataFactory.defaultAdrEp(ADR_3, EPG_GREY).build();
+        Endpoints endpoints =
+                new EndpointsBuilder()
+                    .setAddressEndpoints(
+                            new AddressEndpointsBuilder().setAddressEndpoint(ImmutableList.of(ep1, ep2, ep3)).build())
+                    .build();
+        rendererManager.endpointsUpdated(endpoints);
+
+        AddressEndpointLocation ep1Loc = TestDataFactory.defaultAdrEpLoc(ep1.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep2Loc = TestDataFactory.defaultAdrEpLoc(ep2.getKey(), REG_LOC_NODE_PATH_1).build();
+        AddressEndpointLocation ep3Loc = TestDataFactory.defaultAdrEpLoc(ep3.getKey(), REG_LOC_NODE_PATH_1).build();
+        EndpointLocations endpointLocations = new EndpointLocationsBuilder()
+            .setAddressEndpointLocation(ImmutableList.of(ep1Loc, ep2Loc, ep3Loc)).build();
+        rendererManager.endpointLocationsUpdated(endpointLocations);
+
+        // EP1 as renderer endpoint
+        RendererConfigurationBuilder rendererPolicyBuilder = new RendererConfigurationBuilder();
+        rendererManager.resolveRendererConfigForEndpoint(ep1, rendererPolicyBuilder);
+        ImmutableTable<RendererEndpointKey, PeerEndpointKey, Set<RuleGroupWithRendererEndpointParticipation>> policiesByEpAndPeerEp =
+                rendererPolicyBuilder.getPoliciesByEpAndPeerEp();
+        assertFalse(policiesByEpAndPeerEp.isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtEp().isEmpty());
+        assertTrue(rendererPolicyBuilder.getPoliciesByEpAndPeerExtConEp().isEmpty());
+        assertEquals(1, policiesByEpAndPeerEp.rowKeySet().size());
+        assertEquals(2, policiesByEpAndPeerEp.columnKeySet().size());
+        // check EP1--EPG_BLUE---SUBJECT_1---(P)EPG_PURPLE--EP2
+        // check EP1--EPG_RED----SUBJECT_2---(P)EPG_GREY--EP2
+        RendererEndpointKey ep1RendererEpKey = AddressEndpointUtils.toRendererEpKey(ep1.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsRow(ep1RendererEpKey));
+        PeerEndpointKey ep2PeerEpKey = AddressEndpointUtils.toPeerEpKey(ep2.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsColumn(ep2PeerEpKey));
+        Set<RuleGroupWithRendererEndpointParticipation> ep1Ep2RuleGrpsWithEpPartic =
+                policiesByEpAndPeerEp.get(ep1RendererEpKey, ep2PeerEpKey);
+        assertEquals(2, ep1Ep2RuleGrpsWithEpPartic.size());
+        assertTrue(ep1Ep2RuleGrpsWithEpPartic.contains(RendererConfigurationBuilder
+            .toRuleGroupWithRendererEndpointParticipation(ruleGrp1.getKey(), EndpointPolicyParticipation.CONSUMER)));
+        assertTrue(ep1Ep2RuleGrpsWithEpPartic.contains(RendererConfigurationBuilder
+            .toRuleGroupWithRendererEndpointParticipation(ruleGrp2.getKey(), EndpointPolicyParticipation.CONSUMER)));
+        // check EP1--EPG_RED----SUBJECT_2---(P)EPG_GREY--EP3
+        PeerEndpointKey ep3PeerEpKey = AddressEndpointUtils.toPeerEpKey(ep3.getKey());
+        assertTrue(policiesByEpAndPeerEp.containsColumn(ep3PeerEpKey));
+        Set<RuleGroupWithRendererEndpointParticipation> ep1Ep3RuleGrpsWithEpPartic =
+                policiesByEpAndPeerEp.get(ep1RendererEpKey, ep3PeerEpKey);
+        assertEquals(1, ep1Ep3RuleGrpsWithEpPartic.size());
+        assertTrue(ep1Ep3RuleGrpsWithEpPartic.contains(RendererConfigurationBuilder
+            .toRuleGroupWithRendererEndpointParticipation(ruleGrp2.getKey(), EndpointPolicyParticipation.CONSUMER)));
+    }
+
+}
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/TestDataFactory.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/TestDataFactory.java
new file mode 100644 (file)
index 0000000..b4e8812
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.renderer;
+
+import java.util.Arrays;
+
+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.ForwardingContextContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationBuilder;
+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.address.endpoints.AddressEndpointKey;
+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.endpoints.containment.endpoints.ContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocationsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.ContextType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestDataFactory {
+
+    public static final TenantId TENANT_ID = new TenantId("cisco_tenant");
+    public static final ActionDefinitionId AD_1 = new ActionDefinitionId("ad_1");
+    public static final ActionName AN_1 = new ActionName("an_1");
+    public static final ClassifierDefinitionId CD_1 = new ClassifierDefinitionId("cd_1");
+    public static final ClassifierName CN_1 = new ClassifierName("cn_1");
+    public static final ContextId CTX_1 = new ContextId("ctx_1");
+
+    public static AddressEndpointLocationBuilder defaultAdrEpLoc(AddressEndpointKey adrEpKey, LocationType realLoc,
+            InternalLocation... relativeLocs) {
+        AddressEndpointLocationBuilder result =
+                new AddressEndpointLocationBuilder().setContextType(adrEpKey.getContextType())
+                    .setContextId(adrEpKey.getContextId())
+                    .setAddressType(adrEpKey.getAddressType())
+                    .setAddress(adrEpKey.getAddress())
+                    .setAbsoluteLocation(new AbsoluteLocationBuilder().setLocationType(realLoc).build());
+        if (relativeLocs != null) {
+            result.setRelativeLocations(
+                    new RelativeLocationsBuilder().setInternalLocation(Arrays.asList(relativeLocs)).build());
+        }
+        return result;
+    }
+
+    public static ContainmentEndpointLocationBuilder defaultContEpLoc(ContainmentEndpointKey contEpKey,
+            InternalLocation... relativeLocs) {
+        ContainmentEndpointLocationBuilder result = new ContainmentEndpointLocationBuilder()
+            .setContextType(contEpKey.getContextType()).setContextId(contEpKey.getContextId()).setRelativeLocations(
+                    new RelativeLocationsBuilder().setInternalLocation(Arrays.asList(relativeLocs)).build());
+        return result;
+    }
+
+    public static AddressEndpointBuilder defaultAdrEp(String address, EndpointGroupId... epgs) {
+        return new AddressEndpointBuilder().setContextType(DummyContextType.class)
+            .setContextId(CTX_1)
+            .setAddressType(DummyAddressType.class)
+            .setAddress(address)
+            .setTenant(TENANT_ID)
+            .setEndpointGroup(Arrays.asList(epgs))
+            .setNetworkContainment(
+                    new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
+                        .setContextType(DummyContextType.class).setContextId(CTX_1).build()).build());
+    }
+
+    public static ContainmentEndpointBuilder defaultContEp(EndpointGroupId... epgs) {
+        return new ContainmentEndpointBuilder().setContextType(DummyContextType.class)
+            .setContextId(CTX_1)
+            .setTenant(TENANT_ID)
+            .setEndpointGroup(Arrays.asList(epgs))
+            .setNetworkContainment(
+                    new NetworkContainmentBuilder().setContainment(new ForwardingContextContainmentBuilder()
+                        .setContextType(DummyContextType.class).setContextId(CTX_1).build()).build());
+    }
+
+    public static ResolvedRuleBuilder defaultResolvedRule(RuleName ruleName) {
+        Action action = new ActionBuilder().setActionDefinitionId(AD_1).setName(AN_1).setOrder(0).build();
+        Classifier classifier = new ClassifierBuilder().setClassifierDefinitionId(CD_1)
+            .setName(CN_1)
+            .setDirection(Direction.In)
+            .build();
+        return new ResolvedRuleBuilder().setName(ruleName)
+            .setOrder(0)
+            .setAction(ImmutableList.of(action))
+            .setClassifier(ImmutableList.of(classifier));
+    }
+
+    public static PolicyRuleGroupBuilder defaultPolicyRuleGrp(ContractId contractId, SubjectName subjectName,
+            ResolvedRule... resolvedRules) {
+        return new PolicyRuleGroupBuilder().setTenantId(TENANT_ID)
+            .setContractId(contractId)
+            .setSubjectName(subjectName)
+            .setResolvedRule(Arrays.asList(resolvedRules));
+    }
+
+    public static ResolvedPolicyBuilder defaultResolvedPolicy(EndpointGroupId consEpg, EndpointGroupId provEpg,
+            PolicyRuleGroup... policyRuleGrps) {
+        PolicyRuleGroupWithEndpointConstraints blueRuleGrpWithoutCons =
+                new PolicyRuleGroupWithEndpointConstraintsBuilder().setPolicyRuleGroup(Arrays.asList(policyRuleGrps))
+                    .build();
+        return new ResolvedPolicyBuilder().setConsumerEpgId(consEpg)
+            .setConsumerTenantId(TENANT_ID)
+            .setProviderEpgId(provEpg)
+            .setProviderTenantId(TENANT_ID)
+            .setPolicyRuleGroupWithEndpointConstraints(ImmutableList.of(blueRuleGrpWithoutCons));
+    }
+
+    public static abstract class DummyContextType extends ContextType {
+    };
+    public static abstract class DummyAddressType extends AddressType {
+    };
+}