Solved Bug 6302- 71/48371/4
authorMufaddal Makati <m.makati@cablelabs.com>
Mon, 7 Nov 2016 21:50:57 +0000 (14:50 -0700)
committerMufaddal Makati <m.makati@cablelabs.com>
Tue, 22 Nov 2016 18:28:37 +0000 (11:28 -0700)
Updated Packetcable project to replace DataChangeListener (deprecated)
with DataTreeChangeListener

Change-Id: Id59cff4b0e09bcff48c131a0541406358b6aa008
Signed-off-by: Mufaddal Makati <m.makati@cablelabs.com>
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java [deleted file]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java

diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataChangeListener.java
deleted file mode 100644 (file)
index b099471..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2015 CableLabs and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.packetcable.provider;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromMap;
-import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromSet;
-import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.logChange;
-import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.relativeComplement;
-
-import com.google.common.collect.Maps;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author rvail
- */
-public abstract class AbstractDataChangeListener<T extends DataObject> implements DataChangeListener {
-
-    protected final Logger logger = LoggerFactory.getLogger(getClass());
-
-    private final Class<T> tClass;
-
-    public AbstractDataChangeListener(Class<T> tClass) {
-        this.tClass = checkNotNull(tClass);
-    }
-
-    @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
-        logger.debug("############{}.onDataChanged()", getClass().getSimpleName());
-        logChange(logger, asyncDataChangeEvent);
-
-        final Map<InstanceIdentifier<?>, DataObject> allCreatedData = asyncDataChangeEvent.getCreatedData();
-        final Map<InstanceIdentifier<?>, DataObject> allOriginalData = asyncDataChangeEvent.getOriginalData();
-        final Map<InstanceIdentifier<?>, DataObject> allUpdatedData = asyncDataChangeEvent.getUpdatedData();
-
-        // UpdatedData also contains all data that was created, remove it to get the set of only updated data
-        final Map<InstanceIdentifier<?>, DataObject> trueUpdatedData =
-                relativeComplement(allCreatedData, allUpdatedData);
-        final Map<InstanceIdentifier<?>, DataObject> trueOriginalData =
-                relativeComplement(allCreatedData, allOriginalData);
-
-        if (!allCreatedData.isEmpty()) {
-            final Map<InstanceIdentifier<T>, T> createdTs = collectTypeFromMap(tClass, allCreatedData);
-
-            if (createdTs.isEmpty()) {
-                // this should not happen since this object only listens for changes in one tree
-                logger.warn("Expected created {}(s) but none were found: {}", tClass.getSimpleName(), allCreatedData);
-            }
-            else {
-                handleCreatedData(createdTs);
-            }
-        }
-
-        if (!trueUpdatedData.isEmpty()) {
-            final Map<InstanceIdentifier<T>, T> updatedTs = collectTypeFromMap(tClass, trueUpdatedData);
-            if (updatedTs.isEmpty()) {
-                // this should not happen since this object should only listen for changes in its tree
-                logger.warn("Expected updated {}(s) but none were found: {}", tClass.getSimpleName(), trueUpdatedData);
-            }
-            else {
-
-                final Map<InstanceIdentifier<T>, T> originalTs = collectTypeFromMap(tClass, trueOriginalData);
-                for (InstanceIdentifier<T> iid : updatedTs.keySet()) {
-                    if (!originalTs.containsKey(iid)) {
-                        logger.warn("No original data for updated object {}", iid);
-                    }
-                }
-
-                handleUpdatedData(updatedTs, originalTs);
-            }
-        }
-
-        final Set<InstanceIdentifier<?>> allRemovedPaths = asyncDataChangeEvent.getRemovedPaths();
-        if (!allRemovedPaths.isEmpty()) {
-            final Set<InstanceIdentifier<T>> removedTPaths = collectTypeFromSet(tClass, allRemovedPaths);
-            if (removedTPaths.isEmpty()) {
-                // this should not happen since this object should only listen for changes in its tree
-                logger.warn("Expected removed {} but none were found: {}", tClass.getSimpleName(), allRemovedPaths);
-            }
-
-            Map<InstanceIdentifier<T>, T> originalTData = Maps.newHashMapWithExpectedSize(removedTPaths.size());
-            for (InstanceIdentifier<T> iid : removedTPaths) {
-                if (allOriginalData.containsKey(iid)) {
-
-                    originalTData.put(iid, (T) allOriginalData.get(iid));
-                }
-            }
-
-            handleRemovedData(removedTPaths, originalTData);
-        }
-    }
-
-    protected abstract void handleCreatedData(final Map<InstanceIdentifier<T>, T> createdData);
-
-    protected abstract void handleUpdatedData(final Map<InstanceIdentifier<T>, T> updatedData,
-            final Map<InstanceIdentifier<T>, T> originalData);
-
-    protected abstract void handleRemovedData(final Set<InstanceIdentifier<T>> removedPaths,
-            final Map<InstanceIdentifier<T>, T> originalData);
-
-
-
-}
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/AbstractDataTreeChangeListener.java
new file mode 100644 (file)
index 0000000..8f5a98b
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015 CableLabs and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.packetcable.provider;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromMap;
+import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromSet;
+import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.logChange;
+import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.relativeComplement;
+
+import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Collection;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.packetcable.provider.validation.DataValidator;
+import org.opendaylight.controller.packetcable.provider.validation.ValidationException;
+import org.opendaylight.controller.packetcable.provider.validation.Validator;
+import org.opendaylight.controller.packetcable.provider.validation.ValidatorProvider;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+
+/**
+ * @author rvail
+ * @author mmakati
+ */
+public abstract class AbstractDataTreeChangeListener<T extends DataObject> implements DataTreeChangeListener<T> {
+
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private final Class<T> tClass;
+
+    private final DataValidator dataValidator;
+
+    public AbstractDataTreeChangeListener(Class<T> tClass,DataValidator dataValidator) {
+        this.tClass = checkNotNull(tClass);
+        this.dataValidator = checkNotNull(dataValidator);
+    }
+
+    private ValidationException validateData(final DataTreeModification<T> change){
+        InstanceIdentifier iid = change.getRootPath().getRootIdentifier();
+
+        try {
+            // getDataAfter should only remove null if the data was removed, but we don't validate on remove.
+            dataValidator.validate(iid, change.getRootNode().getDataAfter(), Validator.Extent.NODE_AND_SUBTREE);
+        }
+        catch (ValidationException e) {
+            logger.debug("invalid data: {}", change.getRootNode().getDataAfter(), e);
+            return e;
+        }
+        return null;
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<T>> changes)
+    {
+        Map<DataTreeModification<T>, ValidationException> exceptionMap = Maps.newHashMap();
+        for (final DataTreeModification<T> change : changes) {
+            final DataObjectModification<T> root = change.getRootNode();
+            switch (root.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                    try{
+                        ValidationException validationException = validateData(change);
+                        if(validationException != null){
+                            handleInvalidData(change,validationException);
+                        }
+                        else {
+                            handleUpdatedData(change);
+                        }
+                    }catch (NoSuchElementException e) {
+                        logger.error("Unable to find validator for data: {}", change.getRootNode().getDataAfter(), e);
+                    }
+                    break;
+                case WRITE:
+                    try{
+                        ValidationException validationException = validateData(change);
+                        if(validationException != null){
+                            handleInvalidData(change,validationException);
+                        }
+                        else {
+                            // Treat an overwrite as an update
+                            boolean update = change.getRootNode().getDataBefore() != null;
+                            if (update) {
+                                handleUpdatedData(change);
+                            } else {
+                                handleCreatedData(change);
+                            }
+                        }
+                    }catch (NoSuchElementException e) {
+                        logger.error("Unable to find validator for data: {}", change.getRootNode().getDataAfter(), e);
+                    }
+                    break;
+                case DELETE:
+                    handleRemovedData(change);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+    protected abstract void handleCreatedData(final DataTreeModification<T> change);
+
+    protected abstract void handleUpdatedData(final DataTreeModification<T> change);
+
+    protected abstract void handleRemovedData(final DataTreeModification<T> change);
+
+    protected abstract void handleInvalidData(final DataTreeModification<T> change, ValidationException validationException);
+
+
+}
index a1e0c3f7db4dc5c4975ae1c6315ddaa09227af23..a0f57847b2bbd11fecdf398850e706d9106a2521 100644 (file)
@@ -36,8 +36,10 @@ import java.util.concurrent.Future;
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.ThreadSafe;
 
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 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;
@@ -139,11 +141,11 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
     private RoutedRpcRegistration<PacketcableService> rpcRegistration;
 
     // Data change listeners/registrations
-    private final CcapsDataChangeListener ccapsDataChangeListener = new CcapsDataChangeListener();
-    private final QosDataChangeListener qosDataChangeListener = new QosDataChangeListener();
+    private final CcapsDataTreeChangeListener ccapsDataTreeChangeListener = new CcapsDataTreeChangeListener();
+    private final QosDataTreeChangeListener qosDataTreeChangeListener = new QosDataTreeChangeListener();
 
-    private ListenerRegistration<DataChangeListener> ccapsDataChangeListenerRegistration;
-    private ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration;
+    private ListenerRegistration<DataTreeChangeListener> ccapsDataTreeChangeListenerRegistration;
+    private ListenerRegistration<DataTreeChangeListener> qosDataTreeChangeListenerRegistration;
 
     /**
      * Constructor
@@ -160,14 +162,17 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
         dataBroker = session.getSALService(DataBroker.class);
 
         mdsalUtils = new MdsalUtils(dataBroker);
+        final DataTreeIdentifier<Ccap> ccapsDataTreeIid =
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, ccapsIID.child(Ccap.class));
 
-        ccapsDataChangeListenerRegistration =
-                dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, ccapsIID.child(Ccap.class),
-                        ccapsDataChangeListener, DataBroker.DataChangeScope.SUBTREE);
+        final DataTreeIdentifier<Gate> appDataTreeIid =
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                        qosIID.child(Apps.class).child(App.class).child(Subscribers.class).child(Subscriber.class).child(Gates.class).child(Gate.class));
 
-        qosDataChangeListenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                PacketcableProvider.qosIID.child(Apps.class).child(App.class), qosDataChangeListener,
-                DataBroker.DataChangeScope.SUBTREE);
+        ccapsDataTreeChangeListenerRegistration =
+                dataBroker.registerDataTreeChangeListener(ccapsDataTreeIid, new CcapsDataTreeChangeListener());
+
+        qosDataTreeChangeListenerRegistration = dataBroker.registerDataTreeChangeListener(appDataTreeIid, new QosDataTreeChangeListener());
 
         rpcRegistration = session.addRoutedRpcImplementation(PacketcableService.class, this);
         logger.info("onSessionInitiated().rpcRgistration: {}", rpcRegistration);
@@ -179,12 +184,12 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
      */
     @Override
     public void close() throws ExecutionException, InterruptedException {
-        if (ccapsDataChangeListenerRegistration != null) {
-            ccapsDataChangeListenerRegistration.close();
+        if (ccapsDataTreeChangeListenerRegistration != null) {
+            ccapsDataTreeChangeListenerRegistration.close();
         }
 
-        if (qosDataChangeListenerRegistration != null) {
-            qosDataChangeListenerRegistration.close();
+        if (qosDataTreeChangeListenerRegistration != null) {
+            qosDataTreeChangeListenerRegistration.close();
         }
     }
 
@@ -305,68 +310,54 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
     // ValidationException does not need to be thrown again
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-    private <T extends DataObject> void saveErrors(@Nonnull Map<InstanceIdentifier<T>, ValidationException> errorMap,
-                                                   @Nonnull Map<InstanceIdentifier<T>, T> dataMap) {
+    private <T extends DataObject> void saveErrors(@Nonnull DataTreeModification<T> change, ValidationException exception) {
 
         final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
+        InstanceIdentifier<T> iid = change.getRootPath().getRootIdentifier();
+        //final ValidationException exception = exceptionMap.get(change);
+        final T badData = change.getRootNode().getDataAfter();
 
-        for (InstanceIdentifier<T> iid : errorMap.keySet()) {
-
-            final ValidationException exception = errorMap.get(iid);
-            final T badData = dataMap.get(iid);
-
-            if (!badData.getImplementedInterface().isAssignableFrom(iid.getTargetType())) {
-                // InstanceIdentifier<T> does not have the same type as the DataObject
-                logger.error("Bad InstanceIdentifier to DataObject mapping, {} : {}", iid, badData);
-                continue;
-            }
-
-            if (badData instanceof Ccap) {
-                final Ccap ccap = (Ccap) badData;
-
-                final Ccap opperationalCcap =
-                        new CcapBuilder().setCcapId(ccap.getCcapId()).setError(exception.getErrorMessages()).build();
-
+        if (badData instanceof Ccap) {
+            final Ccap ccap = (Ccap) badData;
 
-                // type match between iid and badData is done at start of loop
-                @SuppressWarnings("unchecked") final InstanceIdentifier<Ccap> ccapIID = (InstanceIdentifier<Ccap>) iid;
-                writeTransaction.put(LogicalDatastoreType.OPERATIONAL, ccapIID, opperationalCcap);
-            } else if (badData instanceof Gate) {
-                final Gate gate = (Gate) badData;
+            final Ccap opperationalCcap =
+                    new CcapBuilder().setCcapId(ccap.getCcapId()).setError(exception.getErrorMessages()).build();
 
-                final Gate operationalGate =
-                        new GateBuilder().setGateId(gate.getGateId()).setError(exception.getErrorMessages()).build();
+            @SuppressWarnings("unchecked") final InstanceIdentifier<Ccap> ccapIID = (InstanceIdentifier<Ccap>) change;
+            writeTransaction.put(LogicalDatastoreType.OPERATIONAL, ccapIID, opperationalCcap);
+        } else if (badData instanceof Gate) {
+            final Gate gate = (Gate) badData;
 
-                final Gates operationalGates =
-                        new GatesBuilder().setGate(Collections.singletonList(operationalGate)).build();
+            final Gate operationalGate =
+                    new GateBuilder().setGateId(gate.getGateId()).setError(exception.getErrorMessages()).build();
 
-                final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(iid.firstIdentifierOf(Subscriber.class));
-                final Subscriber operationalSubscriber =
-                        new SubscriberBuilder().setSubscriberId(subscriberKey.getSubscriberId())
-                                .setGates(operationalGates)
-                                .build();
+            final Gates operationalGates =
+                    new GatesBuilder().setGate(Collections.singletonList(operationalGate)).build();
 
-                final Subscribers operationalSubscribers =
-                        new SubscribersBuilder().setSubscriber(Collections.singletonList(operationalSubscriber))
-                                .build();
+            final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(iid.firstIdentifierOf(Subscriber.class));
+            final Subscriber operationalSubscriber =
+                    new SubscriberBuilder().setSubscriberId(subscriberKey.getSubscriberId())
+                            .setGates(operationalGates)
+                            .build();
 
-                final InstanceIdentifier<App> appIID = iid.firstIdentifierOf(App.class);
-                final AppKey appKey = InstanceIdentifier.keyOf(appIID);
-                final App operationalApp =
-                        new AppBuilder().setAppId(appKey.getAppId()).setSubscribers(operationalSubscribers).build();
+            final Subscribers operationalSubscribers =
+                    new SubscribersBuilder().setSubscriber(Collections.singletonList(operationalSubscriber))
+                            .build();
 
+            final InstanceIdentifier<App> appIID = iid.firstIdentifierOf(App.class);
+            final AppKey appKey = InstanceIdentifier.keyOf(appIID);
+            final App operationalApp =
+                    new AppBuilder().setAppId(appKey.getAppId()).setSubscribers(operationalSubscribers).build();
 
-                writeTransaction.put(LogicalDatastoreType.OPERATIONAL, appIID, operationalApp);
-            } else {
-                // If you get here a developer forgot to add a type above
-                logger.error("Unexpected type requested for error saving: {}", badData);
-                throw new IllegalStateException("Unsupported type for error saving");
-            }
 
+            writeTransaction.put(LogicalDatastoreType.OPERATIONAL, appIID, operationalApp);
+        } else {
+            // If you get here a developer forgot to add a type above
+            logger.error("Unexpected type requested for error saving: {}", badData);
+            throw new IllegalStateException("Unsupported type for error saving");
         }
 
-
         CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
 
         try {
@@ -523,322 +514,260 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
     /**
      * Listener for the packetcable:ccaps tree
      */
-    private class CcapsDataChangeListener extends AbstractDataChangeListener<Ccap> {
-
-        private final DataValidator ccapsDataValidator = new DataValidator(new CcapsValidatorProviderFactory().build());
+    private class CcapsDataTreeChangeListener extends AbstractDataTreeChangeListener<Ccap> {
 
         private final Set<InstanceIdentifier<Ccap>> updateQueue = Sets.newConcurrentHashSet();
 
-        public CcapsDataChangeListener() {
-            super(Ccap.class);
+        public CcapsDataTreeChangeListener() {
+            super(Ccap.class,new DataValidator(new CcapsValidatorProviderFactory().build()));
         }
 
         @Override
-        protected void handleCreatedData(final Map<InstanceIdentifier<Ccap>, Ccap> createdCcaps) {
-            if (createdCcaps.isEmpty()) {
-                return;
-            }
+        protected void handleCreatedData(final DataTreeModification<Ccap> change) {
+            final Ccap ccap = change.getRootNode().getDataAfter();
+            InstanceIdentifier<Ccap> iid = change.getRootPath().getRootIdentifier();
 
-            final Map<InstanceIdentifier<Ccap>, ValidationException> errorMap =
-                    ccapsDataValidator.validateOneType(createdCcaps, Validator.Extent.NODE_AND_SUBTREE);
-
-            // validate all new objects an update operational datastore
-            if (!errorMap.isEmpty()) {
-                // bad data write errors to operational datastore
-                saveErrors(errorMap, createdCcaps);
-            }
-
-            if (createdCcaps.size() > errorMap.size()) {
-                final Map<InstanceIdentifier<Ccap>, Ccap> goodData =
-                        Maps.newHashMapWithExpectedSize(createdCcaps.size() - errorMap.size());
-                for (InstanceIdentifier<Ccap> iid : createdCcaps.keySet()) {
-                    if (!errorMap.containsKey(iid)) {
-                        goodData.put(iid, createdCcaps.get(iid));
-                    }
-                }
-                addNewCcaps(goodData);
+            // add service
+            if (pcmmServiceMap.containsKey(ccap.getCcapId())) {
+                logger.error("Already monitoring CCAP - " + ccap);
+                return;
             }
-        }
-
-        private void addNewCcaps(final Map<InstanceIdentifier<Ccap>, Ccap> goodData) {
-            for (InstanceIdentifier<Ccap> iid : goodData.keySet()) {
-                final Ccap ccap = goodData.get(iid);
-
-                // add service
-                if (pcmmServiceMap.containsKey(ccap.getCcapId())) {
-                    logger.error("Already monitoring CCAP - " + ccap);
-                    continue;
-                }
-                final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
-                // TODO - may want to use the AMID but for the client type but probably not???
+            final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
+            // TODO - may want to use the AMID but for the client type but probably not???
 /*
-                            final PCMMService pcmmService = new PCMMService(
-                                    thisCcap.getAmId().getAmType().shortValue(), thisCcap);
+                    final PCMMService pcmmService = new PCMMService(
+                            thisCcap.getAmId().getAmType().shortValue(), thisCcap);
 */
-                ConnectionBuilder connectionBuilder = new ConnectionBuilder();
-                String message = pcmmService.addCcap();
-                if (message.contains("200 OK")) {
-                    pcmmServiceMap.put(ccap.getCcapId(), pcmmService);
-                    ccapMap.put(ccap.getCcapId(), ccap);
-                    updateCcapMaps(ccap);
-                    logger.info("Created CCAP: {}/{} : {}", iid, ccap, message);
-                    logger.info("Created CCAP: {} : {}", iid, message);
-
-                    connectionBuilder.setConnected(true).setError(Collections.<String>emptyList());
-                } else {
-                    logger.error("Create CCAP Failed: {} : {}", iid, message);
-
-                    connectionBuilder.setConnected(false).setError(Collections.singletonList(message));
-                }
+            ConnectionBuilder connectionBuilder = new ConnectionBuilder();
+            String message = pcmmService.addCcap();
+            if (message.contains("200 OK")) {
+                pcmmServiceMap.put(ccap.getCcapId(), pcmmService);
+                ccapMap.put(ccap.getCcapId(), ccap);
+                updateCcapMaps(ccap);
+                logger.info("Created CCAP: {}/{} : {}", iid, ccap, message);
+                logger.info("Created CCAP: {} : {}", iid, message);
+
+                connectionBuilder.setConnected(true).setError(Collections.<String>emptyList());
+            } else {
+                logger.error("Create CCAP Failed: {} : {}", iid, message);
 
-                //register rpc
-                logger.info("Registering CCAP Routed RPC Path...");
-                rpcRegistration.registerPath(CcapContext.class, iid);
+                connectionBuilder.setConnected(false).setError(Collections.singletonList(message));
+            }
 
-                Optional<Ccap> optionalCcap = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
+            //register rpc
+            logger.info("Registering CCAP Routed RPC Path...");
+            rpcRegistration.registerPath(CcapContext.class, iid);
 
-                final CcapBuilder responseCcapBuilder;
-                if (optionalCcap.isPresent()) {
-                    responseCcapBuilder = new CcapBuilder(optionalCcap.get());
-                } else {
-                    responseCcapBuilder = new CcapBuilder();
-                    responseCcapBuilder.setCcapId(ccap.getCcapId());
-                }
-
-                responseCcapBuilder.setConnection(connectionBuilder.build());
+            Optional<Ccap> optionalCcap = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
 
-                mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, iid, responseCcapBuilder.build());
+            final CcapBuilder responseCcapBuilder;
+            if (optionalCcap.isPresent()) {
+                responseCcapBuilder = new CcapBuilder(optionalCcap.get());
+            } else {
+                responseCcapBuilder = new CcapBuilder();
+                responseCcapBuilder.setCcapId(ccap.getCcapId());
             }
 
+            responseCcapBuilder.setConnection(connectionBuilder.build());
+
+            mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, iid, responseCcapBuilder.build());
         }
 
         @Override
-        protected void handleUpdatedData(final Map<InstanceIdentifier<Ccap>, Ccap> updatedCcaps,
-                                         final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
-
+        protected void handleUpdatedData(final DataTreeModification<Ccap> change) {
+            //final Ccap ccap = (Ccap) change.getRootNode().getIdentifier();
+            InstanceIdentifier<Ccap> iid = change.getRootPath().getRootIdentifier();
             // TODO actually support updates
-
             // update operation not allowed -- restore the original config object and complain
-            for (final Map.Entry<InstanceIdentifier<Ccap>, Ccap> entry : updatedCcaps.entrySet()) {
-                if (!originalCcaps.containsKey(entry.getKey())) {
-                    logger.error("No original data found for supposedly updated data: {}", entry.getValue());
-                    continue;
-                }
 
-                // If this notification is coming from our modification ignore it.
-                if (updateQueue.contains(entry.getKey())) {
-                    updateQueue.remove(entry.getKey());
-                    continue;
-                }
+            // If this notification is coming from our modification ignore it.
+            if (updateQueue.contains(iid)) {
+                updateQueue.remove(iid);
+                return;
+            }
 
-                final Ccap originalCcap = originalCcaps.get(entry.getKey());
-                //final Ccap updatedCcap = entry.getValue();
+            final Ccap originalCcap = change.getRootNode().getDataBefore();
+            //final Ccap updatedCcap = entry.getValue();
 
-                //register rpc
-                logger.info("Registering CCAP Routed RPC Path...");
-                rpcRegistration.registerPath(CcapContext.class, entry.getKey());
+            //register rpc
+            logger.info("Registering CCAP Routed RPC Path...");
+            rpcRegistration.registerPath(CcapContext.class, iid);
 
-                // restore the original data
-                updateQueue.add(entry.getKey());
-                mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalCcap);
-                logger.error("CCAP update not permitted {}", entry.getKey());
-            }
+            // restore the original data
+            updateQueue.add(iid);
+            mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, originalCcap);
+            logger.error("CCAP update not permitted {}", iid);
         }
 
         @Override
-        protected void handleRemovedData(final Set<InstanceIdentifier<Ccap>> removedCcapPaths,
-                                         final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
+        protected void handleRemovedData(final DataTreeModification<Ccap> change) {
 
-            for (InstanceIdentifier<Ccap> iid : removedCcapPaths) {
-                final Ccap nukedCcap = originalCcaps.get(iid);
-                removeCcapFromAllMaps(nukedCcap);
+            InstanceIdentifier<Ccap> iid = change.getRootPath().getRootIdentifier();
+            final Ccap nukedCcap = change.getRootNode().getDataBefore();
+            removeCcapFromAllMaps(nukedCcap);
 
-                //unregister ccap rpc path
-                logger.info("Un-Registering CCAP Routed RPC Path...");
-                rpcRegistration.unregisterPath(CcapContext.class, iid);
+            //unregister ccap rpc path
+            logger.info("Un-Registering CCAP Routed RPC Path...");
+            rpcRegistration.unregisterPath(CcapContext.class, iid);
 
-                mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, iid);
+            mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, iid);
 
-                // clean up ccaps level if it is now empty
-                executor.execute(new CcapsCleaner(iid));
-            }
+            // clean up ccaps level if it is now empty
+            executor.execute(new CcapsCleaner(iid));
+        }
 
+        @Override
+        protected void handleInvalidData(final DataTreeModification<Ccap> change, ValidationException validationException){
+            // bad data write errors to operational datastore
+            saveErrors(change, validationException);
         }
-    }
 
+    }
 
-    private class QosDataChangeListener extends AbstractDataChangeListener<Gate> {
+    private class QosDataTreeChangeListener extends AbstractDataTreeChangeListener<Gate> {
 
-        private final DataValidator qosDataValidator = new DataValidator(new QosValidatorProviderFactory().build());
         private final Set<InstanceIdentifier<Gate>> updateQueue = Sets.newConcurrentHashSet();
 
-        public QosDataChangeListener() {
-            super(Gate.class);
+        public QosDataTreeChangeListener() {
+            super(Gate.class,new DataValidator(new QosValidatorProviderFactory().build()));
         }
 
         @Override
-        protected void handleCreatedData(final Map<InstanceIdentifier<Gate>, Gate> createdData) {
-
-            final Map<InstanceIdentifier<Gate>, ValidationException> errorMap =
-                    qosDataValidator.validateOneType(createdData, Validator.Extent.NODE_AND_SUBTREE);
-
-            // validate all new objects an update operational datastore
-            if (!errorMap.isEmpty()) {
-                // bad data write errors to operational datastore
-                saveErrors(errorMap, createdData);
-            }
-
-            if (createdData.size() > errorMap.size()) {
-                final Map<InstanceIdentifier<Gate>, Gate> goodData =
-                        Maps.newHashMapWithExpectedSize(createdData.size() - errorMap.size());
-                for (InstanceIdentifier<Gate> iid : createdData.keySet()) {
-                    if (!errorMap.containsKey(iid)) {
-                        goodData.put(iid, createdData.get(iid));
-                    }
-                }
-                addNewGates(goodData);
-            }
-
-        }
-
-        private void addNewGates(final Map<InstanceIdentifier<Gate>, Gate> createdGates) {
+        protected void handleCreatedData(final DataTreeModification<Gate> change) {
 
-            for (InstanceIdentifier<Gate> gateIID : createdGates.keySet()) {
-                final Gate newGate = createdGates.get(gateIID);
+            InstanceIdentifier<Gate> gateIID = change.getRootPath().getRootIdentifier();
+            final Gate newGate = change.getRootNode().getDataAfter();
 
-                final String newGatePathStr = makeGatePathString(gateIID);
+            final String newGatePathStr = makeGatePathString(gateIID);
 
-                // if a new app comes along add RPC registration
-                final InstanceIdentifier<App> appIID = gateIID.firstIdentifierOf(App.class);
-                // TBD verify if App ID exists first
+            // if a new app comes along add RPC registration
+            final InstanceIdentifier<App> appIID = gateIID.firstIdentifierOf(App.class);
+            // TBD verify if App ID exists first
 
-                //register appID RPC path
-                logger.info("Registering App Routed RPC Path...");
-                rpcRegistration.registerPath(AppContext.class, appIID);
-
-                final InstanceIdentifier<Subscriber> subscriberIID = gateIID.firstIdentifierOf(Subscriber.class);
-                final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID);
-                final InetAddress subscriberAddr = getInetAddress(subscriberKey.getSubscriberId());
-                if (subscriberAddr == null) {
-                    final String msg = String.format("subscriberId must be a valid ipaddress: %s",
-                            subscriberKey.getSubscriberId());
-                    logger.error(msg);
-                    saveGateError(gateIID, newGatePathStr, msg);
-                    continue;
-                }
+            //register appID RPC path
+            logger.info("Registering App Routed RPC Path...");
+            rpcRegistration.registerPath(AppContext.class, appIID);
 
-                final Ccap ccap = findCcapForSubscriberId(subscriberAddr);
-                if (ccap == null) {
-                    final String msg = String.format("Unable to find Ccap for subscriber %s: @ %s",
-                            subscriberKey.getSubscriberId(), newGatePathStr);
-                    logger.error(msg);
-                    saveGateError(gateIID, newGatePathStr, msg);
-                    continue;
-                }
+            final InstanceIdentifier<Subscriber> subscriberIID = gateIID.firstIdentifierOf(Subscriber.class);
+            final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID);
+            final InetAddress subscriberAddr = getInetAddress(subscriberKey.getSubscriberId());
+            if (subscriberAddr == null) {
+                final String msg = String.format("subscriberId must be a valid ipaddress: %s",
+                        subscriberKey.getSubscriberId());
+                logger.error(msg);
+                saveGateError(gateIID, newGatePathStr, msg);
+                return;
+            }
 
-                final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId());
-                if (pcmmService == null) {
-                    final String msg =
-                            String.format("Unable to locate PCMM Service for CCAP: %s ; with subscriber: %s", ccap,
-                                    subscriberKey.getSubscriberId());
-                    logger.error(msg);
-                    saveGateError(gateIID, newGatePathStr, msg);
-                    continue;
-                }
+            final Ccap ccap = findCcapForSubscriberId(subscriberAddr);
+            if (ccap == null) {
+                final String msg = String.format("Unable to find Ccap for subscriber %s: @ %s",
+                        subscriberKey.getSubscriberId(), newGatePathStr);
+                logger.error(msg);
+                saveGateError(gateIID, newGatePathStr, msg);
+                return;
+            }
 
-                //
-                // set up gate builder with known fields (and some empty ones)
-                //
-                final GateBuilder gateBuilder = new GateBuilder();
-                gateBuilder.setGateId(newGate.getGateId())
-                        .setGatePath(newGatePathStr)
-                        .setCcapId(ccap.getCcapId())
-                        .setTrafficProfile(newGate.getTrafficProfile())
-                        .setClassifiers(newGate.getClassifiers())
-                        .setGateSpec(newGate.getGateSpec())
-                        .setCopsGateState("")
-                        .setCopsGateTimeInfo("")
-                        .setCopsGateUsageInfo("");
+            final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId());
+            if (pcmmService == null) {
+                final String msg =
+                        String.format("Unable to locate PCMM Service for CCAP: %s ; with subscriber: %s", ccap,
+                                subscriberKey.getSubscriberId());
+                logger.error(msg);
+                saveGateError(gateIID, newGatePathStr, msg);
+                return;
+            }
 
-                //
-                // Right now only ServiceClassName traffic Profile is supported. This logic needs to
-                // be updated when the yang traffic-profile is extended to support new types
-                // Override requested Direction using the Ccap configuration information about SCNs and
-                // their configured direction.
-                //
-                final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName();
-                final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap);
-                if (scnDirection == null) {
-                    final String msg =
+            //
+            // set up gate builder with known fields (and some empty ones)
+            //
+            final GateBuilder gateBuilder = new GateBuilder();
+            gateBuilder.setGateId(newGate.getGateId())
+                    .setGatePath(newGatePathStr)
+                    .setCcapId(ccap.getCcapId())
+                    .setTrafficProfile(newGate.getTrafficProfile())
+                    .setClassifiers(newGate.getClassifiers())
+                    .setGateSpec(newGate.getGateSpec())
+                    .setCopsGateState("")
+                    .setCopsGateTimeInfo("")
+                    .setCopsGateUsageInfo("");
+
+            //
+            // Right now only ServiceClassName traffic Profile is supported. This logic needs to
+            // be updated when the yang traffic-profile is extended to support new types
+            // Override requested Direction using the Ccap configuration information about SCNs and
+            // their configured direction.
+            //
+            final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName();
+            final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap);
+            if (scnDirection == null) {
+                final String msg =
                         String.format("SCN %s not found on CCAP %s for %s", scn, ccap.getCcapId(), newGatePathStr);
-                    logger.error(msg);
-                    saveGateError(gateIID, newGatePathStr, msg);
-                    continue;
-                }
-                
-                //
-                // since we may be modifying the contents of the original request GateSpec
-                // to update flow direction (based on the ccap SCN configuration) we need to
-                // rebuild the requested gate spec and replace the existing one in the gate builder
-                //
-                final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
-                gateSpecBuilder.setDirection(scnDirection);
-                gateSpecBuilder.setDscpTosMask(newGate.getGateSpec().getDscpTosMask());
-                gateSpecBuilder.setDscpTosOverwrite(newGate.getGateSpec().getDscpTosOverwrite());
-                final GateSpec gateSpec = gateSpecBuilder.build();
-                gateBuilder.setGateSpec(gateSpec);
-
-                //
-                // build the gate to be requested
-                //
-                gateBuilder.setTimestamp(getNowTimeStamp());
+                logger.error(msg);
+                saveGateError(gateIID, newGatePathStr, msg);
+                return;
+            }
 
-                final Gate requestGate = gateBuilder.build();
+            //
+            // since we may be modifying the contents of the original request GateSpec
+            // to update flow direction (based on the ccap SCN configuration) we need to
+            // rebuild the requested gate spec and replace the existing one in the gate builder
+            //
+            final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
+            gateSpecBuilder.setDirection(scnDirection);
+            gateSpecBuilder.setDscpTosMask(newGate.getGateSpec().getDscpTosMask());
+            gateSpecBuilder.setDscpTosOverwrite(newGate.getGateSpec().getDscpTosOverwrite());
+            final GateSpec gateSpec = gateSpecBuilder.build();
+            gateBuilder.setGateSpec(gateSpec);
+
+            //
+            // build the gate to be requested
+            //
+            gateBuilder.setTimestamp(getNowTimeStamp());
+
+            final Gate requestGate = gateBuilder.build();
+
+            //
+            // send gate request to Ccap
+            //
+            PCMMService.GateSendStatus status =
+                    pcmmService.sendGateSet(newGatePathStr, subscriberAddr, requestGate);
+            if (status.didSucceed()) {
+                gateMap.put(newGatePathStr, requestGate);
+                gateCcapMap.put(newGatePathStr, ccap.getCcapId());
 
                 //
-                // send gate request to Ccap
+                // inquire as to the status, and implementation info of the requested gate
                 //
-                PCMMService.GateSendStatus status =
-                        pcmmService.sendGateSet(newGatePathStr, subscriberAddr, requestGate);
-                if (status.didSucceed()) {
-                    gateMap.put(newGatePathStr, requestGate);
-                    gateCcapMap.put(newGatePathStr, ccap.getCcapId());
+                PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr);
 
+                if (infoStatus.didSucceed()) {
                     //
-                    // inquire as to the status, and implementation info of the requested gate
+                    // update builder with info for operational storage
                     //
-                    PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr);
-
-                    if (infoStatus.didSucceed()) {
-                        //
-                        // update builder with info for operational storage
-                        //
-                        gateBuilder.setCopsGateState(
-                                infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason())
-                                .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo())
-                                .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo())
-                                .setCopsGateId(status.getCopsGateId());
-                    } else {
-                        List<String> errors = new ArrayList<>(2);
-
-                        // Keep GateSetErrors
-                        if (gateBuilder.getError() != null) {
-                            errors.addAll(gateBuilder.getError());
-                        }
+                    gateBuilder.setCopsGateState(
+                            infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason())
+                            .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo())
+                            .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo())
+                            .setCopsGateId(status.getCopsGateId());
+                } else {
+                    List<String> errors = new ArrayList<>(2);
 
-                        errors.add(infoStatus.getMessage());
-                        gateBuilder.setError(errors);
+                    // Keep GateSetErrors
+                    if (gateBuilder.getError() != null) {
+                        errors.addAll(gateBuilder.getError());
                     }
-                }
-                else {
-                    gateBuilder.setError(Collections.singletonList(status.getMessage()));
-                }
 
-                Gate operationalGate = gateBuilder.build();
-
-                mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate);
+                    errors.add(infoStatus.getMessage());
+                    gateBuilder.setError(errors);
+                }
+            }
+            else {
+                gateBuilder.setError(Collections.singletonList(status.getMessage()));
             }
 
+            Gate operationalGate = gateBuilder.build();
+            mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate);
         }
 
         private void saveGateError(@Nonnull final InstanceIdentifier<Gate> gateIID, @Nonnull final String gatePathStr,
@@ -860,67 +789,61 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
         }
 
         @Override
-        protected void handleUpdatedData(final Map<InstanceIdentifier<Gate>, Gate> updatedData,
-                                         final Map<InstanceIdentifier<Gate>, Gate> originalData) {
+        protected void handleUpdatedData(final DataTreeModification<Gate> change) {
+            InstanceIdentifier<Gate> gateIID = change.getRootPath().getRootIdentifier();
+            //final Gate newGate = (Gate) change.getRootNode().getIdentifier();
             // TODO actually support updates
 
             // update operation not allowed -- restore the original config object and complain
-            for (final Map.Entry<InstanceIdentifier<Gate>, Gate> entry : updatedData.entrySet()) {
-                if (!originalData.containsKey(entry.getKey())) {
-                    logger.error("No original data found for supposedly updated data: {}", entry.getValue());
-                    continue;
-                }
-
-                // If this notification is coming from our modification ignore it.
-                if (updateQueue.contains(entry.getKey())) {
-                    updateQueue.remove(entry.getKey());
-                    continue;
-                }
-
-                final Gate originalGate = originalData.get(entry.getKey());
-
-                // restores the original data
-                updateQueue.add(entry.getKey());
-                mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalGate);
-                logger.error("Update not permitted {}", entry.getKey());
 
+            // If this notification is coming from our modification ignore it.
+            if (updateQueue.contains(gateIID)) {
+                updateQueue.remove(gateIID);
+                return;
             }
-        }
 
+            final Gate originalGate = change.getRootNode().getDataBefore();
 
+            // restores the original data
+            updateQueue.add(gateIID);
+            mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, gateIID, originalGate);
+            logger.error("Update not permitted {}", gateIID);
+        }
 
         @Override
-        protected void handleRemovedData(final Set<InstanceIdentifier<Gate>> removedPaths,
-                                         final Map<InstanceIdentifier<Gate>, Gate> originalData) {
-
-            for (final InstanceIdentifier<Gate> removedGateIID : removedPaths) {
+        protected void handleRemovedData(final DataTreeModification<Gate> change) {
+            InstanceIdentifier<Gate> removedGateIID = change.getRootPath().getRootIdentifier();
+            final Gate newGate = change.getRootNode().getDataBefore();
 
-                mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, removedGateIID);
+            mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, removedGateIID);
 
-                executor.execute(new SubscriberCleaner(removedGateIID));
+            executor.execute(new SubscriberCleaner(removedGateIID));
 
-                final String gatePathStr = makeGatePathString(removedGateIID);
+            final String gatePathStr = makeGatePathString(removedGateIID);
 
-                if (gateMap.containsKey(gatePathStr)) {
-                    final Gate thisGate = gateMap.remove(gatePathStr);
-                    final String gateId = thisGate.getGateId();
-                    final String ccapId = gateCcapMap.remove(gatePathStr);
-                    final Ccap thisCcap = ccapMap.get(ccapId);
-                    final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId());
-                    if (service != null) {
-                        service.sendGateDelete(gatePathStr);
-                        logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,thisGate);
-                    } else {
-                        logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
-                                + thisCcap);
-                    }
+            if (gateMap.containsKey(gatePathStr)) {
+                final Gate thisGate = gateMap.remove(gatePathStr);
+                final String gateId = thisGate.getGateId();
+                final String ccapId = gateCcapMap.remove(gatePathStr);
+                final Ccap thisCcap = ccapMap.get(ccapId);
+                final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId());
+                if (service != null) {
+                    service.sendGateDelete(gatePathStr);
+                    logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,thisGate);
+                } else {
+                    logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
+                            + thisCcap);
                 }
-
-
             }
 
         }
 
+        @Override
+        protected void handleInvalidData(final DataTreeModification<Gate> change, ValidationException validationException){
+            // bad data write errors to operational datastore
+            saveErrors(change, validationException);
+        }
+
         private String makeGatePathString(InstanceIdentifier<Gate> iid) {
             final InstanceIdentifier<App> appIID = iid.firstIdentifierOf(App.class);
             final AppKey appKey = InstanceIdentifier.keyOf(appIID);
@@ -934,7 +857,6 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
         }
     }
 
-
     @Override
     public Future<RpcResult<CcapSetConnectionOutput>> ccapSetConnection(CcapSetConnectionInput input) {
         // TODO refactor this method into smaller parts
@@ -1378,7 +1300,6 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                 }
             }
         }
-
     }