Update of BaseEndpointRpcRegistry 39/38939/9
authorMichal Cmarada <mcmarada@cisco.com>
Wed, 18 May 2016 13:22:30 +0000 (15:22 +0200)
committerMartin Sunal <msunal@cisco.com>
Wed, 18 May 2016 14:11:31 +0000 (14:11 +0000)
- adding Verification of RPC Input
- adding update of Endpoints in op DS
- Unit tests

Change-Id: Ic709f7a47f3aeed7e46201d17ed54d297c8031bc
Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistry.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistryTest.java

index d92edd19666014b4fe059472cc34c11fa7f1888f..899e29e8b00b081ded0f84d0f8535382b4983cdf 100644 (file)
@@ -9,38 +9,55 @@
 package org.opendaylight.groupbasedpolicy.base_endpoint;
 
 import com.google.common.base.Function;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 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.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentation;
 import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentationRegistry;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.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.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.child.endpoints.ChildEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -48,10 +65,13 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Future;
 
+import javax.annotation.Nullable;
+
 public class BaseEndpointRpcRegistry
-    implements BaseEndpointService, BaseEndpointRendererAugmentationRegistry, AutoCloseable {
+        implements BaseEndpointService, BaseEndpointRendererAugmentationRegistry, AutoCloseable {
 
-    static final ConcurrentMap<String, BaseEndpointRendererAugmentation> registeredRenderers = new ConcurrentHashMap<>();
+    static final ConcurrentMap<String, BaseEndpointRendererAugmentation> registeredRenderers =
+            new ConcurrentHashMap<>();
     private static final Logger LOG = LoggerFactory.getLogger(BaseEndpointRpcRegistry.class);
     private final DataBroker dataProvider;
     private final BindingAwareBroker.RpcRegistration<BaseEndpointService> rpcRegistration;
@@ -65,33 +85,11 @@ public class BaseEndpointRpcRegistry
     };
 
     public BaseEndpointRpcRegistry(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) {
-        this.dataProvider = dataProvider;
-
-        if (rpcRegistry != null) {
-            rpcRegistration = rpcRegistry.addRpcImplementation(BaseEndpointService.class, this);
-            LOG.debug("Added Endpoints RPC Implementation Correctly");
-        } else {
-            rpcRegistration = null;
-        }
-
-        if (dataProvider != null) {
-            InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class).build();
-            WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
-            t.put(LogicalDatastoreType.OPERATIONAL, iid, new EndpointsBuilder().build());
-            CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
-            Futures.addCallback(f, new FutureCallback<Void>() {
-
-                @Override
-                public void onFailure(Throwable t) {
-                    LOG.error("Could not write Endpoints base container", t);
-                }
+        Preconditions.checkNotNull(dataProvider);
+        Preconditions.checkNotNull(rpcRegistry);
 
-                @Override
-                public void onSuccess(Void result) {
-                    LOG.info("Endpoints container write successful");
-                }
-            });
-        }
+        this.dataProvider = dataProvider;
+        this.rpcRegistration = rpcRegistry.addRpcImplementation(BaseEndpointService.class, this);
     }
 
     /**
@@ -104,7 +102,7 @@ public class BaseEndpointRpcRegistry
     public void register(BaseEndpointRendererAugmentation baseEndpointRendererAugmentation) {
         if (baseEndpointRendererAugmentation != null) {
             registeredRenderers.putIfAbsent(baseEndpointRendererAugmentation.getClass().getName(),
-                baseEndpointRendererAugmentation);
+                    baseEndpointRendererAugmentation);
             LOG.info("Registered {}", baseEndpointRendererAugmentation.getClass().getName());
         }
     }
@@ -138,25 +136,294 @@ public class BaseEndpointRpcRegistry
         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
 
         List<ContainmentEndpointReg> endpoints = input.getContainmentEndpointReg();
-        for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) {
-            long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp();
-            ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build();
-            t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint,
-                    true);
-        }
+        ListenableFuture<RpcResult<Void>> failResult = verifyRegisterEndpointInput(input);
+        if (failResult == null) {
+            for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) {
+                long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp();
+                ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build();
+                t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint,
+                        true);
+
+                updateContainmentEndpointRegChilds(t, endpoint);
+            }
+
+            List<AddressEndpointReg> addressEndpoints = input.getAddressEndpointReg();
+            for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) {
+                long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp();
+                AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build();
+                t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint,
+                        true);
+
+                updateAddressEndpointRegChilds(t, endpoint);
 
-        List<AddressEndpointReg> addressEndpoints = input.getAddressEndpointReg();
-        for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) {
-            long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp();
-            AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build();
-            t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint, true);
+                updateAddressEndpointRegParents(t, endpoint);
+            }
+        } else {
+            return failResult;
         }
 
         ListenableFuture<Void> r = t.submit();
         return Futures.transform(r, futureTrans);
     }
 
+    private void updateContainmentEndpointRegChilds(WriteTransaction t, ContainmentEndpoint containmentEndpoint) {
+        ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        for (ChildEndpoint child : nullToEmpty(containmentEndpoint.getChildEndpoint())) {
+            AddressEndpointKey key = new AddressEndpointKey(child.getAddress(), child.getAddressType(),
+                    child.getContextId(), child.getContextType());
+            Optional<AddressEndpoint> addressEndpointOptional = DataStoreHelper
+                .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key), readTransaction);
+
+            if (addressEndpointOptional.isPresent()) {
+                ParentEndpointChoice parentEndpointChoice = addressEndpointOptional.get().getParentEndpointChoice();
+                List<ParentContainmentEndpoint> parentContainmentEndpoints =
+                        getParentContainmentEndpoints(parentEndpointChoice);
+
+                ParentContainmentEndpoint parentContainmentEndpoint =
+                        new ParentContainmentEndpointBuilder().setContextId(containmentEndpoint.getContextId())
+                            .setContextType(containmentEndpoint.getContextType())
+                            .build();
+
+                if (!nullToEmpty(parentContainmentEndpoints).contains(parentContainmentEndpoint)) {
+                    parentContainmentEndpoints.add(parentContainmentEndpoint);
+                    AddressEndpoint updatedAddressEndpoint = new AddressEndpointBuilder(addressEndpointOptional.get())
+                        .setParentEndpointChoice(new ParentContainmentEndpointCaseBuilder()
+                            .setParentContainmentEndpoint(parentContainmentEndpoints).build())
+                        .build();
+
+                    t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key), updatedAddressEndpoint);
+                }
+            }
+        }
+    }
+
+    private ListenableFuture<RpcResult<Void>> verifyRegisterEndpointInput(RegisterEndpointInput input) {
+        ListenableFuture<RpcResult<Void>> result;
+        List<AddressEndpointReg> addressEndpointRegs = nullToEmpty(input.getAddressEndpointReg());
+        List<ContainmentEndpointReg> containmentEndpointRegs = nullToEmpty(input.getContainmentEndpointReg());
+
+        for (AddressEndpointReg addressEndpointReg : nullToEmpty(addressEndpointRegs)) {
+            result = verifyAddressEndpointChilds(addressEndpointRegs, addressEndpointReg);
+            if (result != null) {
+                return result;
+            }
+
+            result = verifyAddressEndpointParents(addressEndpointRegs, addressEndpointReg);
+            if (result != null) {
+                return result;
+            }
+        }
+
+        result = verifyContainmentEndpointChilds(addressEndpointRegs, containmentEndpointRegs);
+        if (result != null) {
+            return result;
+        }
+
+        return null;
+    }
+
+    private ListenableFuture<RpcResult<Void>> verifyContainmentEndpointChilds(
+            List<AddressEndpointReg> addressEndpointRegs, List<ContainmentEndpointReg> containmentEndpointRegs) {
+        for (ContainmentEndpointReg containmentEndpointReg : nullToEmpty(containmentEndpointRegs)) {
+            for (ChildEndpoint childEndpoint : nullToEmpty(containmentEndpointReg.getChildEndpoint())) {
+                AddressEndpointRegKey key = new AddressEndpointRegKey(childEndpoint.getAddress(),
+                        childEndpoint.getAddressType(), childEndpoint.getContextId(), childEndpoint.getContextType());
+                AddressEndpointReg addressEndpointRegChild = findAddressEndpointReg(key, addressEndpointRegs);
+                if (addressEndpointRegChild == null) {
+                    // todo this can be optimized if we move this to
+                    // updateContainmentEndpointRegChilds and verify child in one step with update.
+                    Optional<AddressEndpoint> addressEndpointOptional =
+                            DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                                    IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(),
+                                            key.getAddressType(), key.getContextId(), key.getContextType())),
+                                    dataProvider.newReadOnlyTransaction());
+                    if (!addressEndpointOptional.isPresent()) {
+                        LOG.debug("Child AddressEndpoint {} does not exist in RPC and DS.", childEndpoint);
+                        return buildFailFeature(
+                                String.format("Child AddressEndpoint %s does not exist in RPC and DS.", childEndpoint));
+                    }
+                } else {
+
+                    if (!containmentEndpointReg.getKey().equals(new ContainmentEndpointRegKey(
+                            addressEndpointRegChild.getContextId(), addressEndpointRegChild.getContextType()))) {
+                        LOG.debug(
+                                "Child AddressEndpoint {} in ContainmentEndpoint->ChildEndpoints does not contain a valid ContainmentEndpointRegKey.",
+                                addressEndpointRegChild);
+                        return buildFailFeature(String
+                            .format("AddressEndpoint in ContainmentEndpoint->ChildEndpoints does not contain a valid ContainmentEndpointRegKey."
+                                    + "\nChild element: %s", addressEndpointRegChild));
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private ListenableFuture<RpcResult<Void>> verifyAddressEndpointParents(List<AddressEndpointReg> addressEndpointRegs,
+            AddressEndpointReg addressEndpointReg) {
+        ParentEndpointChoice parentEndpointChoice = addressEndpointReg.getParentEndpointChoice();
+        List<ParentEndpoint> parentEndpoints;
+        parentEndpoints =
+                (parentEndpointChoice instanceof ParentEndpointCase) ? ((ParentEndpointCase) parentEndpointChoice)
+                    .getParentEndpoint() : null;
+
+        for (ParentEndpoint parentEndpoint : nullToEmpty(parentEndpoints)) {
+            AddressEndpointRegKey key = new AddressEndpointRegKey(parentEndpoint.getAddress(),
+                    parentEndpoint.getAddressType(), parentEndpoint.getContextId(), parentEndpoint.getContextType());
+            AddressEndpointReg addressEndpointRegParent = findAddressEndpointReg(key, addressEndpointRegs);
+
+            if (addressEndpointRegParent == null) {
+                // todo this can be optimized if we move this to updateAddressEndpointRegParents and
+                // verify child in one step with update.
+                Optional<AddressEndpoint> addressEndpointOptional =
+                        DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                                IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(),
+                                        key.getAddressType(), key.getContextId(), key.getContextType())),
+                                dataProvider.newReadOnlyTransaction());
+                if (!addressEndpointOptional.isPresent()) {
+                    LOG.debug("Parent AddressEndpoint {} does not exist in RPC and DS.", parentEndpoint);
+                    return buildFailFeature(
+                            String.format("Parent AddressEndpoint %s does not exist in RPC and DS.", parentEndpoint));
+                }
+            } else {
+
+                List<ChildEndpoint> childEndpoints = addressEndpointRegParent.getChildEndpoint();
+
+                if (!nullToEmpty(childEndpoints).contains(new ChildEndpointBuilder(addressEndpointReg).build())) {
+                    LOG.debug("Parent AddressEndpoint {} does not contain a valid child AddressEndpoint.",
+                            addressEndpointRegParent);
+                    return buildFailFeature(String.format(
+                            "Parent AddressEndpoint does not contain a valid child AddressEndpoint."
+                                    + "\nParent AddressEndpoint: %s" + "\nChild AddressEndpoint: %s",
+                            addressEndpointRegParent, addressEndpointReg));
+                }
+            }
+        }
+        return null;
+    }
+
+    private ListenableFuture<RpcResult<Void>> verifyAddressEndpointChilds(List<AddressEndpointReg> addressEndpointRegs,
+            AddressEndpointReg addressEndpointReg) {
+        for (ChildEndpoint childEndpoint : nullToEmpty(addressEndpointReg.getChildEndpoint())) {
+            AddressEndpointRegKey key = new AddressEndpointRegKey(childEndpoint.getAddress(),
+                    childEndpoint.getAddressType(), childEndpoint.getContextId(), childEndpoint.getContextType());
+            AddressEndpointReg addressEndpointRegChild = findAddressEndpointReg(key, addressEndpointRegs);
+            if (addressEndpointRegChild == null) {
+                // todo this can be optimized if we move this to updateAddressEndpointRegChilds and
+                // verify child in one step with update.
+                Optional<AddressEndpoint> addressEndpointOptional =
+                        DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                                IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(),
+                                        key.getAddressType(), key.getContextId(), key.getContextType())),
+                                dataProvider.newReadOnlyTransaction());
+                if (!addressEndpointOptional.isPresent()) {
+                    LOG.debug("Child AddressEndpoint {} does not exist in RPC and DS.", childEndpoint);
+                    return buildFailFeature(
+                            String.format("Child AddressEndpoint %s does not exist in RPC and DS.", childEndpoint));
+                }
+            } else {
+
+                ParentEndpointChoice parentEndpointChoice = addressEndpointRegChild.getParentEndpointChoice();
+
+                if (!(parentEndpointChoice instanceof ParentEndpointCase)) {
+                    LOG.debug("Child AddressEndpoint {} does not contain list of parent elements.", childEndpoint);
+                    return buildFailFeature(String.format(
+                            "Child AddressEndpoint does not contain list of parent elements." + "\nChild element: %s",
+                            childEndpoint));
+                }
+
+                List<ParentEndpoint> parentEndpoints =
+                        nullToEmpty(((ParentEndpointCase) parentEndpointChoice).getParentEndpoint());
+                if (!parentEndpoints.contains(new ParentEndpointBuilder(addressEndpointReg).build())) {
+                    LOG.debug("Child AddressEndpoint {} does not contain a valid parent AddressEndpoint.",
+                            addressEndpointRegChild);
+                    return buildFailFeature(String.format(
+                            "Child AddressEndpoint does not contain a valid parent AddressEndpoint."
+                                    + "\nChild element: %s" + "\nparent AddressEndpoint: %s",
+                            addressEndpointRegChild, addressEndpointReg));
+                }
+            }
+        }
+        return null;
+    }
+
+    private AddressEndpointReg findAddressEndpointReg(AddressEndpointRegKey key, List<AddressEndpointReg> addressEndpointRegs) {
+        for (AddressEndpointReg addressEndpointReg : addressEndpointRegs) {
+            if (addressEndpointReg.getKey().equals(key)) {
+                return addressEndpointReg;
+            }
+        }
+        return null;
+    }
+
+    private void updateAddressEndpointRegParents(WriteTransaction t, AddressEndpoint endpoint) {
+        ParentEndpointCase parentEndpointCase = (ParentEndpointCase) endpoint.getParentEndpointChoice();
+        List<ParentEndpoint> parentEndpoints;
+        ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        parentEndpoints = getParentEndpoints(parentEndpointCase);
+
+        for (ParentEndpoint parent : nullToEmpty(parentEndpoints)) {
+            Optional<AddressEndpoint> addressEndpointOptional =
+                    DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                            IidFactory.addressEndpointIid(new AddressEndpointKey(parent.getAddress(),
+                                    parent.getAddressType(), parent.getContextId(), parent.getContextType())),
+                            readTransaction);
+
+            if (addressEndpointOptional.isPresent()) {
+
+                List<ChildEndpoint> childEndpoints;
+
+                childEndpoints = (addressEndpointOptional.get() == null || addressEndpointOptional.get()
+                    .getChildEndpoint() == null) ? new ArrayList<>() : addressEndpointOptional.get().getChildEndpoint();
+
+                ChildEndpoint childEndpoint = new ChildEndpointBuilder(endpoint).build();
+                if (!childEndpoints.contains(childEndpoint)) {
+                    childEndpoints.add(childEndpoint);
+                    AddressEndpoint parentAddressEndpoint = new AddressEndpointBuilder(addressEndpointOptional.get())
+                        .setChildEndpoint(childEndpoints).build();
+                    t.put(LogicalDatastoreType.OPERATIONAL,
+                            IidFactory.addressEndpointIid(parentAddressEndpoint.getKey()), parentAddressEndpoint);
+                }
+            }
+        }
+    }
+
+    private void updateAddressEndpointRegChilds(WriteTransaction t, AddressEndpoint endpoint) {
+        ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        for (ChildEndpoint child : nullToEmpty(endpoint.getChildEndpoint())) {
+            Optional<AddressEndpoint> addressEndpointOptional =
+                    DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                            IidFactory.addressEndpointIid(new AddressEndpointKey(child.getAddress(),
+                                    child.getAddressType(), child.getContextId(), child.getContextType())),
+                            readTransaction);
+
+            if (addressEndpointOptional.isPresent()) {
+                ParentEndpointCase parentEndpointCase =
+                        (ParentEndpointCase) addressEndpointOptional.get().getParentEndpointChoice();
+                List<ParentEndpoint> parentEndpoints;
+
+                parentEndpoints = getParentEndpoints(parentEndpointCase);
+
+                ParentEndpoint parentEndpoint = new ParentEndpointBuilder(endpoint).build();
+                if (!parentEndpoints.contains(parentEndpoint)) {
+                    parentEndpoints.add(parentEndpoint);
+                    AddressEndpoint childAddressEndpoint =
+                            new AddressEndpointBuilder(addressEndpointOptional.get())
+                                .setParentEndpointChoice(
+                                        new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build())
+                                .build();
+                    t.put(LogicalDatastoreType.OPERATIONAL,
+                            IidFactory.addressEndpointIid(childAddressEndpoint.getKey()), childAddressEndpoint);
+                }
+            }
+        }
+    }
+
     private ContainmentEndpointBuilder buildContainmentEndpoint(ContainmentEndpointReg input) {
+
         ContainmentEndpointBuilder eb = new ContainmentEndpointBuilder().setChildEndpoint(input.getChildEndpoint())
             .setCondition(input.getCondition())
             .setContextType(input.getContextType())
@@ -165,7 +432,8 @@ public class BaseEndpointRpcRegistry
             .setKey(new ContainmentEndpointKey(input.getContextId(), input.getContextType()))
             .setNetworkContainment(input.getNetworkContainment())
             .setTenant(input.getTenant())
-            .setTimestamp(input.getTimestamp());
+            .setTimestamp(input.getTimestamp())
+            .setChildEndpoint(input.getChildEndpoint());
 
         for (Map.Entry<String, BaseEndpointRendererAugmentation> entry : registeredRenderers.entrySet()) {
             try {
@@ -225,18 +493,157 @@ public class BaseEndpointRpcRegistry
             AddressEndpointKey key = new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), ae.getContextId(),
                     ae.getContextType());
             t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key));
+
+            updateAddressEndpointUnregChilds(t, ae);
+
+            updateAddressEndpointUnregParents(t, ae);
         }
 
         List<ContainmentEndpointUnreg> endpoints = input.getContainmentEndpointUnreg();
         for (ContainmentEndpointUnreg ce : nullToEmpty(endpoints)) {
             ContainmentEndpointKey key = new ContainmentEndpointKey(ce.getContextId(), ce.getContextType());
             t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(key));
+
+            updateContainmentEndpointUnregChilds(t, ce);
         }
 
         ListenableFuture<Void> r = t.submit();
         return Futures.transform(r, futureTrans);
     }
 
+    private void updateAddressEndpointUnregParents(WriteTransaction t, AddressEndpointUnreg ae) {
+        ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        Optional<AddressEndpoint> addressEndpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(),
+                        ae.getContextId(), ae.getContextType())),
+                readTransaction);
+
+        if (addressEndpointOptional.isPresent()) {
+            ParentEndpointCase parentEndpointCase =
+                    (ParentEndpointCase) addressEndpointOptional.get().getParentEndpointChoice();
+            List<ParentEndpoint> parentEndpoints;
+
+            parentEndpoints = getParentEndpoints(parentEndpointCase);
+
+            for (ParentEndpoint parentEndpoint : parentEndpoints) {
+                Optional<AddressEndpoint> parentAddressEndpointOptional =
+                        DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                                IidFactory.addressEndpointIid(new AddressEndpointKey(parentEndpoint.getAddress(),
+                                        parentEndpoint.getAddressType(), parentEndpoint.getContextId(),
+                                        parentEndpoint.getContextType())),
+                                readTransaction);
+
+                AddressEndpoint parent =
+                        parentAddressEndpointOptional.isPresent() ? parentAddressEndpointOptional.get() : null;
+
+                ChildEndpoint endpointToRemove = new ChildEndpointBuilder(addressEndpointOptional.get()).build();
+
+                if (parent != null && nullToEmpty(parent.getChildEndpoint()).contains(endpointToRemove)) {
+                    parent.getChildEndpoint().remove(endpointToRemove);
+                    t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(parent.getKey()), parent);
+                }
+
+            }
+        }
+    }
+
+    private void updateAddressEndpointUnregChilds(WriteTransaction t, AddressEndpointUnreg ae) {
+        ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        Optional<AddressEndpoint> addressEndpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(),
+                        ae.getContextId(), ae.getContextType())),
+                readTransaction);
+
+        if (addressEndpointOptional.isPresent()) {
+            AddressEndpoint endpoint = addressEndpointOptional.get();
+            List<ChildEndpoint> childEndpoints = endpoint.getChildEndpoint();
+
+            for (ChildEndpoint childEndpoint : nullToEmpty(childEndpoints)) {
+                Optional<AddressEndpoint> childAddressEndpointOptional =
+                        DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                                IidFactory.addressEndpointIid(new AddressEndpointKey(childEndpoint.getAddress(),
+                                        childEndpoint.getAddressType(), childEndpoint.getContextId(),
+                                        childEndpoint.getContextType())),
+                                readTransaction);
+
+                AddressEndpoint child =
+                        childAddressEndpointOptional.isPresent() ? childAddressEndpointOptional.get() : null;
+                ParentEndpointCase parentEndpointCase =
+                        (child != null) ? (ParentEndpointCase) child.getParentEndpointChoice() : null;
+                List<ParentEndpoint> parentEndpoints;
+
+                parentEndpoints = getParentEndpoints(parentEndpointCase);
+
+                ParentEndpoint endpointToRemove = new ParentEndpointBuilder(endpoint).build();
+
+                if (child != null && nullToEmpty(parentEndpoints).contains(endpointToRemove)) {
+                    parentEndpoints.remove(endpointToRemove);
+                    AddressEndpoint newChild =
+                            new AddressEndpointBuilder(child)
+                                .setParentEndpointChoice(
+                                        new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build())
+                                .build();
+
+                    t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(newChild.getKey()), newChild);
+                }
+            }
+        }
+    }
+
+    private void updateContainmentEndpointUnregChilds(WriteTransaction t,
+            ContainmentEndpointUnreg containmentEndpointUnreg) {
+        ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction();
+
+        ContainmentEndpointKey key = new ContainmentEndpointKey(containmentEndpointUnreg.getContextId(),
+                containmentEndpointUnreg.getContextType());
+        Optional<ContainmentEndpoint> containmentEndpointOptional = DataStoreHelper
+            .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(key), readTransaction);
+
+        if (!containmentEndpointOptional.isPresent()) {
+            return;
+        }
+
+        for (ChildEndpoint child : nullToEmpty(containmentEndpointOptional.get().getChildEndpoint())) {
+            AddressEndpointKey aeKey = new AddressEndpointKey(child.getAddress(), child.getAddressType(),
+                    child.getContextId(), child.getContextType());
+            Optional<AddressEndpoint> addressEndpointOptional = DataStoreHelper
+                .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aeKey), readTransaction);
+
+            if (addressEndpointOptional.isPresent()) {
+                ParentEndpointChoice parentEndpointChoice = addressEndpointOptional.get().getParentEndpointChoice();
+                List<ParentContainmentEndpoint> parentContainmentEndpoints;
+                parentContainmentEndpoints = getParentContainmentEndpoints(parentEndpointChoice);
+
+                ParentContainmentEndpoint parentContainmentEndpoint =
+                        new ParentContainmentEndpointBuilder().setContextId(containmentEndpointUnreg.getContextId())
+                            .setContextType(containmentEndpointUnreg.getContextType())
+                            .build();
+                if (nullToEmpty(parentContainmentEndpoints).contains(parentContainmentEndpoint)) {
+                    t.delete(LogicalDatastoreType.OPERATIONAL,
+                            IidFactory.parentContainmentEndpointIid(aeKey, parentContainmentEndpoint.getKey()));
+                }
+            }
+        }
+    }
+
+    private List<ParentContainmentEndpoint> getParentContainmentEndpoints(ParentEndpointChoice parentEndpointChoice) {
+        return (parentEndpointChoice instanceof ParentContainmentEndpointCase) ? ((ParentContainmentEndpointCase) parentEndpointChoice)
+            .getParentContainmentEndpoint() : new ArrayList<>();
+    }
+
+    private List<ParentEndpoint> getParentEndpoints(ParentEndpointCase parentEndpointCase) {
+        return (parentEndpointCase == null
+                || parentEndpointCase.getParentEndpoint() == null) ? new ArrayList<>() : parentEndpointCase
+                    .getParentEndpoint();
+    }
+
+    private ListenableFuture<RpcResult<Void>> buildFailFeature(String message) {
+        return Futures
+            .immediateFuture(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.PROTOCOL, message).build());
+    }
+
     @Override
     public void close() throws Exception {
         if (rpcRegistration != null) {
index 2116d12e1cc838a1f5871b85e630fd7b62c3a503..a9f9e6c6b66c85135632f9bb2be74fc93c0be825 100644 (file)
@@ -17,6 +17,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 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.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointKey;
 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;
@@ -393,6 +395,17 @@ public class IidFactory {
             .build();
     }
 
+    public static InstanceIdentifier<ParentContainmentEndpoint> parentContainmentEndpointIid(
+            AddressEndpointKey addressEndpointKey, ParentContainmentEndpointKey parentContainmentEndpointKey) {
+        return InstanceIdentifier
+            .builder(
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints.class)
+            .child(AddressEndpoints.class)
+            .child(AddressEndpoint.class, addressEndpointKey)
+            .child(ParentContainmentEndpoint.class, parentContainmentEndpointKey)
+            .build();
+    }
+
     public static InstanceIdentifierBuilder<ProviderAddressEndpointLocation> providerAddressEndpointLocationIid(String provider,
             Class<? extends AddressType> addrType, String addr, Class<? extends ContextType> cType,
             ContextId containment) {
index 875043dee9ee3e7eda13ff9b612d1317cf5ebddc..b83bcc5417f6b05d7fc8729ad64a82d18eeedaf4 100644 (file)
 
 package org.opendaylight.groupbasedpolicy.base_endpoint;
 
-import com.google.common.util.concurrent.CheckedFuture;
+import static org.mockito.Mockito.mock;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentation;
-import org.opendaylight.groupbasedpolicy.base_endpoint.BaseEndpointRpcRegistry;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.*;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.ContainmentEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.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.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.child.endpoints.ChildEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnregBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Future;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
-import static org.mockito.internal.verification.VerificationModeFactory.times;
+import javax.annotation.Nonnull;
 
-public class BaseEndpointRpcRegistryTest {
+public class BaseEndpointRpcRegistryTest extends CustomDataBrokerTest {
 
     private static final String MAC_ADDRESS = "01:23:45:67:89:AB";
+    private static final String IP_ADDRESS = "192.168.100.1/24";
     private static final String TENANT = "admin";
     private static final String DOMAIN = "test.domain";
     private static final String CONTEXT_ID = "testContext";
-    private static final String FLOOD_DOMAIN = "testFloodDomain";
+    private static final long timestamp = 1234567890L;
+
+    private enum AddressEndpointRegistration {
+        CHILD, PARENT, BOTH, NONE
+    }
+    private enum AddressEndpointType {
+        L2, L3, BOTH, NONE
+    }
 
     private DataBroker dataProvider;
     private BaseEndpointRendererAugmentation baseEndpointRendererAugmentation;
     private BaseEndpointRpcRegistry baseEndpointRpcRegistry;
+    private AddressEndpoint basel2Ep;
+    private AddressEndpoint basel3Ep;
+    private ContainmentEndpoint baseContainmentEp;
+    private ParentEndpoint basel3Parent;
+    private ChildEndpoint basel2Child;
+
+    @Nonnull
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return ImmutableList.of(Endpoints.class, AddressEndpoints.class, ContainmentEndpoints.class,
+                MacAddressType.class, IpPrefixType.class);
+    }
 
     @Before
     public void init() {
-        dataProvider = mock(DataBroker.class);
+        dataProvider = getDataBroker();
         baseEndpointRendererAugmentation = mock(BaseEndpointRendererAugmentation.class);
-        WriteTransaction wt = newWriteTransactionMock();
         RpcProviderRegistry rpcRegistry = mock(RpcProviderRegistry.class);
 
         baseEndpointRpcRegistry = new BaseEndpointRpcRegistry(dataProvider, rpcRegistry);
+
+        NetworkDomainContainment
+            networkDomainContainment =
+            new NetworkDomainContainmentBuilder().setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(
+                Subnet.class).build();
+
+        basel3Parent = new ParentEndpointBuilder().setAddress(IP_ADDRESS)
+            .setAddressType(IpPrefixType.class)
+            .setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L3Context.class)
+            .build();
+
+        basel2Child = new ChildEndpointBuilder().setAddress(MAC_ADDRESS)
+            .setAddressType(MacAddressType.class)
+            .setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L2FloodDomain.class)
+            .build();
+
+        basel2Ep = new AddressEndpointBuilder().setTimestamp(timestamp)
+            .setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L2FloodDomain.class)
+            .setTenant(new TenantId(TENANT))
+            .setAddress(MAC_ADDRESS)
+            .setAddressType(MacAddressType.class)
+            .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build())
+            .setTimestamp(timestamp)
+            .setParentEndpointChoice(
+                    new ParentEndpointCaseBuilder().setParentEndpoint(Collections.singletonList(basel3Parent)).build())
+            .build();
+
+        basel3Ep = new AddressEndpointBuilder().setTimestamp(timestamp)
+            .setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L3Context.class)
+            .setTenant(new TenantId(TENANT))
+            .setAddress(IP_ADDRESS)
+            .setAddressType(IpPrefixType.class)
+            .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build())
+            .setTimestamp(timestamp)
+            .setChildEndpoint(Collections.singletonList(basel2Child))
+            .build();
+
+        baseContainmentEp = new ContainmentEndpointBuilder().setTimestamp(timestamp)
+            .setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L2FloodDomain.class)
+            .setTenant(new TenantId(TENANT))
+            .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build())
+            .setChildEndpoint(Collections.singletonList(basel2Child))
+            .build();
     }
 
     @Test
@@ -87,60 +179,357 @@ public class BaseEndpointRpcRegistryTest {
 
     @Test
     public void testRegisterEndpoint() throws Exception {
-        WriteTransaction wt = newWriteTransactionMock();
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true);
+
+        baseEndpointRpcRegistry.registerEndpoint(input);
 
-        baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest());
+        ReadOnlyTransaction transaction = dataProvider.newReadOnlyTransaction();
 
-        verify(wt, times(2)).put(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class),
-                any(DataObject.class), eq(true));
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+                L2FloodDomain.class);
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), transaction);
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+
+        if (addressEndpointL2.isPresent()) {
+            Assert.assertEquals(basel2Ep, addressEndpointL2.get());
+        }
+
+        key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class);
+
+        Optional<AddressEndpoint> addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), transaction);
+
+        Assert.assertTrue(addressEndpointL3.isPresent());
+
+        if (addressEndpointL3.isPresent()) {
+            Assert.assertEquals(basel3Ep, addressEndpointL3.get());
+        }
+
+        ContainmentEndpointKey containmentEndpointKey =
+                new ContainmentEndpointKey(new ContextId(CONTEXT_ID), L2FloodDomain.class);
+
+        Optional<ContainmentEndpoint> ContainmentEndpoint = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.containmentEndpointIid(containmentEndpointKey), transaction);
+
+        Assert.assertTrue(ContainmentEndpoint.isPresent());
+
+        if (ContainmentEndpoint.isPresent()) {
+            Assert.assertEquals(baseContainmentEp, ContainmentEndpoint.get());
+        }
     }
 
-    private RegisterEndpointInput createRegisterEndpointInputVariablesForTest() throws Exception {
-        RegisterEndpointInputBuilder registerEndpointInputBuilder = new RegisterEndpointInputBuilder();
-        long timestamp = System.currentTimeMillis();
+    @Test
+    public void testRegisterEndpointWithParentUpdate() throws Exception {
+        setupBasicDataStore();
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.L2, true);
 
-        registerEndpointInputBuilder.setAddressEndpointReg(new ArrayList<>());
-        registerEndpointInputBuilder.setContainmentEndpointReg(new ArrayList<>());
+        baseEndpointRpcRegistry.registerEndpoint(input);
 
-        registerEndpointInputBuilder.getAddressEndpointReg().add(
-                new AddressEndpointRegBuilder().setTimestamp(timestamp)
-                    .setContextId(new ContextId(CONTEXT_ID))
-                    .setContextType(L2FloodDomain.class)
-                    .setTenant(new TenantId(TENANT))
-                    .setAddress(MAC_ADDRESS)
-                    .setAddressType(MacAddressType.class)
-                    .setAddressType(AddressType.class)
-                    .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder()
-                        .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(Subnet.class).build()).build())
-                    .setKey(new AddressEndpointRegKey(MAC_ADDRESS,MacAddressType.class, new ContextId(CONTEXT_ID), L2FloodDomain.class))
-                    .setTimestamp(timestamp).build());
-
-        registerEndpointInputBuilder.getContainmentEndpointReg().add(
-                new ContainmentEndpointRegBuilder()
-                    .setTimestamp(timestamp)
-                    .setContextId(new L2FloodDomainId(FLOOD_DOMAIN))
-                    .setContextType(L2FloodDomain.class)
-                    .setTenant(new TenantId(TENANT))
-                    .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder()
-                        .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(Subnet.class).build()).build())
-                    .setKey(new ContainmentEndpointRegKey(new L2FloodDomainId(FLOOD_DOMAIN),L2FloodDomain.class))
-                    .build());
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+                L2FloodDomain.class);
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
 
-        return registerEndpointInputBuilder.build();
+        Assert.assertTrue(addressEndpointL2.isPresent());
+
+        if (addressEndpointL2.isPresent()) {
+            ParentEndpointCase parentEndpointCase =
+                    (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice();
+            List<ParentEndpoint> parentEndpoints = parentEndpointCase.getParentEndpoint();
+            Assert.assertEquals(parentEndpoints.size(), 1);
+        }
+
+        key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class);
+
+        Optional<AddressEndpoint> addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL3.isPresent());
+
+        if (addressEndpointL3.isPresent()) {
+            Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 1);
+        }
     }
 
     @Test
-    public void testUnregisterEndpoint() throws Exception {
-        WriteTransaction wt = newWriteTransactionMock();
+    public void testRegisterEndpointWithParentUpdateFail() throws Exception {
+        RegisterEndpointInput input = createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH,
+                AddressEndpointType.L2, true);
 
-        UnregisterEndpointInput unregisterEndpointInput = unregisterEndpointInput();
+        Future<RpcResult<Void>> rpcResultFuture = baseEndpointRpcRegistry.registerEndpoint(input);
+
+        Assert.assertFalse(rpcResultFuture.get().isSuccessful());
+        Assert.assertNotNull(rpcResultFuture.get().getErrors());
+        Assert.assertEquals(rpcResultFuture.get().getErrors().size(), 1);
+    }
+
+    @Test
+    public void testRegisterEndpointWithChildUpdate() throws Exception {
+        setupBasicDataStore();
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.L3, true);
 
-        baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInput);
+        baseEndpointRpcRegistry.registerEndpoint(input);
 
-        verify(wt, times(2)).delete(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+                L2FloodDomain.class);
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+
+        if (addressEndpointL2.isPresent()) {
+            ParentEndpointCase parentEndpointCase =
+                    (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice();
+            List<ParentEndpoint> parentEndpoints = parentEndpointCase.getParentEndpoint();
+            Assert.assertEquals(parentEndpoints.size(), 1);
+        }
+
+        key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class);
+
+        Optional<AddressEndpoint> addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL3.isPresent());
+
+        if (addressEndpointL3.isPresent()) {
+            Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 1);
+        }
     }
 
-    private UnregisterEndpointInput unregisterEndpointInput() {
+    @Test
+    public void testRegisterEndpointWithChildUpdateFail() throws Exception {
+        RegisterEndpointInput input = createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH,
+                AddressEndpointType.L3, true);
+
+        Future<RpcResult<Void>> rpcResultFuture = baseEndpointRpcRegistry.registerEndpoint(input);
+
+        Assert.assertFalse(rpcResultFuture.get().isSuccessful());
+        Assert.assertNotNull(rpcResultFuture.get().getErrors());
+        Assert.assertEquals(rpcResultFuture.get().getErrors().size(), 1);
+    }
+
+    private void setupBasicDataStore() throws Exception {
+        InstanceIdentifier<Endpoints> id = InstanceIdentifier.builder(Endpoints.class).build();
+        dataProvider.newWriteOnlyTransaction().delete(LogicalDatastoreType.OPERATIONAL, id);
+
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.NONE, AddressEndpointType.BOTH, true);
+
+        baseEndpointRpcRegistry.registerEndpoint(input);
+
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+                L2FloodDomain.class);
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+
+        if (addressEndpointL2.isPresent()) {
+            ParentEndpointCase parentEndpointCase =
+                    (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice();
+            Assert.assertEquals(parentEndpointCase.getParentEndpoint().size(), 0);
+        }
+
+        key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class);
+
+        Optional<AddressEndpoint> addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL3.isPresent());
+
+        if (addressEndpointL3.isPresent()) {
+            Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 0);
+        }
+    }
+
+    @Test
+    public void testRegisterEndpointParentFail() throws Exception {
+        Future<RpcResult<Void>> rpcResultFuture =
+                baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest(
+                        AddressEndpointRegistration.PARENT, AddressEndpointType.BOTH, true));
+
+        RpcResult<Void> rpcResult = rpcResultFuture.get();
+
+        Assert.assertFalse(rpcResult.isSuccessful());
+        Assert.assertNull(rpcResult.getResult());
+        Assert.assertEquals(rpcResult.getErrors().size(), 1);
+
+    }
+
+    @Test
+    public void testRegisterEndpointChildFail() throws Exception {
+        Future<RpcResult<Void>> rpcResultFuture =
+                baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest(
+                        AddressEndpointRegistration.CHILD, AddressEndpointType.BOTH, true));
+
+        RpcResult<Void> rpcResult = rpcResultFuture.get();
+
+        Assert.assertFalse(rpcResult.isSuccessful());
+        Assert.assertNull(rpcResult.getResult());
+        Assert.assertEquals(rpcResult.getErrors().size(), 1);
+    }
+
+    @Test
+    public void testUnregisterEndpointWithParent() throws Exception {
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true);
+
+        baseEndpointRpcRegistry.registerEndpoint(input);
+
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+                L2FloodDomain.class);
+        ContainmentEndpointKey cKey = new ContainmentEndpointKey(new ContextId(CONTEXT_ID), L2FloodDomain.class);
+
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+
+        if (addressEndpointL2.isPresent()) {
+            Assert.assertEquals(basel2Ep, addressEndpointL2.get());
+        }
+
+        Optional<ContainmentEndpoint> ContainmentEndpoint = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.containmentEndpointIid(cKey), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(ContainmentEndpoint.isPresent());
+
+        if (ContainmentEndpoint.isPresent()) {
+            Assert.assertEquals(baseContainmentEp, ContainmentEndpoint.get());
+        }
+
+        baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInputParent());
+        Optional<AddressEndpoint> endpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertFalse(endpointOptional.isPresent());
+
+        Optional<ContainmentEndpoint> containmentEndpointOptional =
+                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(cKey),
+                        dataProvider.newReadOnlyTransaction());
+
+        Assert.assertFalse(containmentEndpointOptional.isPresent());
+    }
+
+    @Test
+    public void testUnregisterEndpointWithChild() throws Exception {
+        RegisterEndpointInput input =
+                createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true);
+
+        baseEndpointRpcRegistry.registerEndpoint(input);
+
+        AddressEndpointKey key =
+                new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class);
+
+        Optional<AddressEndpoint> addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL3.isPresent());
+
+        if (addressEndpointL3.isPresent()) {
+            Assert.assertEquals(basel3Ep, addressEndpointL3.get());
+        }
+
+        baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInputChild());
+        Optional<AddressEndpoint> endpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertFalse(endpointOptional.isPresent());
+
+    }
+
+    @Test
+    public void testRegisterContainmentEndpointWithChildFail() throws Exception {
+        Future<RpcResult<Void>> rpcResultFuture =
+                baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest(
+                        AddressEndpointRegistration.NONE, AddressEndpointType.NONE, true));
+
+        RpcResult<Void> rpcResult = rpcResultFuture.get();
+
+        Assert.assertFalse(rpcResult.isSuccessful());
+        Assert.assertNull(rpcResult.getResult());
+        Assert.assertEquals(rpcResult.getErrors().size(), 1);
+    }
+
+    @Test
+    public void testUnregisterContainmentEndpointWithChild() throws Exception {
+        InstanceIdentifier<Endpoints> id = InstanceIdentifier.builder(Endpoints.class).build();
+        dataProvider.newWriteOnlyTransaction().delete(LogicalDatastoreType.OPERATIONAL, id);
+
+        RegisterEndpointInput input =
+            createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.NONE, AddressEndpointType.L2, false);
+
+        baseEndpointRpcRegistry.registerEndpoint(input);
+
+        AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID),
+            L2FloodDomain.class);
+
+        Optional<AddressEndpoint> addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+            IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+        if (addressEndpointL2.isPresent()){
+            ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice();
+            if(parentEndpointChoice instanceof ParentContainmentEndpointCase){
+                ParentContainmentEndpointCase
+                    parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice;
+                Assert.assertNull(parentEndpointCase.getParentContainmentEndpoint());
+            }
+        }
+
+        ContainmentEndpointReg containmentEndpointReg = new ContainmentEndpointRegBuilder().setTimestamp(baseContainmentEp.getTimestamp())
+            .setContextId(baseContainmentEp.getContextId())
+            .setContextType(baseContainmentEp.getContextType())
+            .setTenant(baseContainmentEp.getTenant())
+            .setNetworkContainment(baseContainmentEp.getNetworkContainment())
+            .setChildEndpoint(Collections.singletonList(basel2Child))
+            .build();
+
+        baseEndpointRpcRegistry.registerEndpoint(new RegisterEndpointInputBuilder().setContainmentEndpointReg(Collections.singletonList(containmentEndpointReg)).build());
+
+        addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+            IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+        if (addressEndpointL2.isPresent()) {
+            ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice();
+            if(parentEndpointChoice instanceof ParentContainmentEndpointCase){
+                ParentContainmentEndpointCase
+                    parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice;
+                Assert.assertNotNull(parentEndpointCase.getParentContainmentEndpoint());
+                Assert.assertEquals(parentEndpointCase.getParentContainmentEndpoint().size(),1);
+            }
+        }
+
+        ContainmentEndpointUnreg containmentEndpointUnreg = new ContainmentEndpointUnregBuilder()
+            .setContextId(baseContainmentEp.getContextId())
+            .setContextType(baseContainmentEp.getContextType())
+            .build();
+
+        baseEndpointRpcRegistry.unregisterEndpoint(new UnregisterEndpointInputBuilder().setContainmentEndpointUnreg(Collections.singletonList(containmentEndpointUnreg)).build());
+
+        addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+            IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction());
+
+        Assert.assertTrue(addressEndpointL2.isPresent());
+        if (addressEndpointL2.isPresent()) {
+            ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice();
+            if(parentEndpointChoice instanceof ParentContainmentEndpointCase){
+                ParentContainmentEndpointCase
+                    parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice;
+                Assert.assertNotNull(parentEndpointCase.getParentContainmentEndpoint());
+                Assert.assertEquals(parentEndpointCase.getParentContainmentEndpoint().size(),0);
+            }
+        }
+
+    }
+
+    private UnregisterEndpointInput unregisterEndpointInputParent() {
         UnregisterEndpointInputBuilder builder = new UnregisterEndpointInputBuilder();
 
         builder.setAddressEndpointUnreg(new ArrayList<>());
@@ -158,13 +547,77 @@ public class BaseEndpointRpcRegistryTest {
         return builder.build();
     }
 
-    private WriteTransaction newWriteTransactionMock() {
-        WriteTransaction wt = mock(WriteTransaction.class);
-        CheckedFuture<Void, TransactionCommitFailedException> f = mock(CheckedFuture.class);
+    private UnregisterEndpointInput unregisterEndpointInputChild() {
+        UnregisterEndpointInputBuilder builder = new UnregisterEndpointInputBuilder();
+
+        builder.setAddressEndpointUnreg(new ArrayList<>());
+        builder.setContainmentEndpointUnreg(new ArrayList<>());
 
-        when(dataProvider.newWriteOnlyTransaction()).thenReturn(wt);
-        when(wt.submit()).thenReturn(f);
-        return wt;
+        builder.getAddressEndpointUnreg().add(new AddressEndpointUnregBuilder().setContextId(new ContextId(CONTEXT_ID))
+            .setContextType(L3Context.class)
+            .setAddress(IP_ADDRESS)
+            .setAddressType(IpPrefixType.class)
+            .build());
+
+        return builder.build();
     }
 
+    private RegisterEndpointInput createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration registration,
+            AddressEndpointType type, boolean containmentEpPresent) throws Exception {
+        RegisterEndpointInputBuilder registerEndpointInputBuilder = new RegisterEndpointInputBuilder();
+        long timestamp = System.currentTimeMillis();
+
+        List<ParentEndpoint> parentEndpoints = new ArrayList<>();
+        if (registration == AddressEndpointRegistration.BOTH || registration == AddressEndpointRegistration.PARENT) {
+            parentEndpoints.add(basel3Parent);
+        }
+
+        List<ChildEndpoint> childEndpoints = new ArrayList<>();
+        if (registration == AddressEndpointRegistration.BOTH || registration == AddressEndpointRegistration.CHILD) {
+            childEndpoints.add(basel2Child);
+        }
+
+        registerEndpointInputBuilder.setAddressEndpointReg(new ArrayList<>());
+        registerEndpointInputBuilder.setContainmentEndpointReg(new ArrayList<>());
+
+        if (type == AddressEndpointType.BOTH || type == AddressEndpointType.L2) {
+            registerEndpointInputBuilder.getAddressEndpointReg()
+                .add(new AddressEndpointRegBuilder().setTimestamp(timestamp)
+                    .setContextId(basel2Ep.getContextId())
+                    .setContextType(basel2Ep.getContextType())
+                    .setTenant(basel2Ep.getTenant())
+                    .setAddress(basel2Ep.getAddress())
+                    .setAddressType(basel2Ep.getAddressType())
+                    .setNetworkContainment(basel2Ep.getNetworkContainment())
+                    .setTimestamp(basel2Ep.getTimestamp())
+                    .setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build())
+                    .build());
+        }
+
+        if (type == AddressEndpointType.BOTH || type == AddressEndpointType.L3) {
+            registerEndpointInputBuilder.getAddressEndpointReg()
+                .add(new AddressEndpointRegBuilder().setContextId(basel3Ep.getContextId())
+                    .setContextType(basel3Ep.getContextType())
+                    .setTenant(basel3Ep.getTenant())
+                    .setAddress(basel3Ep.getAddress())
+                    .setAddressType(basel3Ep.getAddressType())
+                    .setNetworkContainment(basel3Ep.getNetworkContainment())
+                    .setTimestamp(basel3Ep.getTimestamp())
+                    .setChildEndpoint(childEndpoints)
+                    .build());
+        }
+
+        if(containmentEpPresent) {
+            registerEndpointInputBuilder.getContainmentEndpointReg()
+                .add(new ContainmentEndpointRegBuilder().setTimestamp(baseContainmentEp.getTimestamp())
+                    .setContextId(baseContainmentEp.getContextId())
+                    .setContextType(baseContainmentEp.getContextType())
+                    .setTenant(baseContainmentEp.getTenant())
+                    .setNetworkContainment(baseContainmentEp.getNetworkContainment())
+                    .setChildEndpoint(Collections.singletonList(basel2Child))
+                    .build());
+        }
+
+        return registerEndpointInputBuilder.build();
+    }
 }