Remove "response" from yang. 39/24439/12
authorAlexis de Talhouët <adetalhouet@inocybe.com>
Wed, 22 Jul 2015 20:00:14 +0000 (16:00 -0400)
committerAlexis de Talhouët <adetalhouet@inocybe.com>
Wed, 12 Aug 2015 19:05:20 +0000 (15:05 -0400)
Once pushing an object to the DS/config, if it's config is not correct,
instead of updating the object by setting the "response" field to know the reason,
the object is deleted and the message that was previously shown in
the "response" is logged at the error level.

This patch also reconciliate CCAP on restart.

Change-Id: I92fbe38d4519d21079341b618e244db8e51cc6c5
Signed-off-by: Alexis de Talhouët <adetalhouet@inocybe.com>
.gitignore
packetcable-policy-model/src/main/yang/packetcable.yang
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/MdsalUtils.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java [deleted file]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/ValidateInstanceData.java

index 930c03372df5090be6d49645a62acfbe8a1068d3..eb56c648930a673f16795d083dcf929bed90de55 100644 (file)
@@ -8,6 +8,7 @@
 .externalToolBuilders
 maven-eclipse.xml
 workspace
+.checkstyle
 
 ## Compilation Files ##
 *.class
@@ -15,6 +16,7 @@ workspace
 target
 target-ide
 MANIFEST.MF
+maven-metadata-local.xml
 
 ## Misc Ignores (OS specific etc) ##
 bin/
index c919acd2f374d9f27b3b424c2a58200107be3c22..52dbed41086c3c75aef2c7f1f52fed01f86684e4 100644 (file)
@@ -95,10 +95,6 @@ module packetcable
                leaf-list downstream-scns {
                        type service-class-name;
                }
-        leaf response {
-            type string;
-            description "HTTP response from the PUT operation provided by the API";
-        }
        }
 
        // PCMM QoS Gates
@@ -151,10 +147,6 @@ module packetcable
                uses pcmm-qos-classifier;
                uses pcmm-qos-ext-classifier;
                uses pcmm-qos-ipv6-classifier;
-               leaf response {
-            type string;
-            description "HTTP response from the PUT operation provided by the API";
-        }
     }
 
     grouping pcmm-qos-gate-spec {
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/MdsalUtils.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/MdsalUtils.java
new file mode 100644 (file)
index 0000000..8f32d0d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 Inocybe 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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class MdsalUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(MdsalUtils.class);
+    private DataBroker databroker = null;
+
+    /**
+     * Class constructor setting the data broker.
+     *
+     * @param dataBroker the {@link org.opendaylight.controller.md.sal.binding.api.DataBroker}
+     */
+    public MdsalUtils(DataBroker dataBroker) {
+        this.databroker = dataBroker;
+    }
+
+    /**
+     * Executes delete as a blocking transaction.
+     *
+     * @param store {@link LogicalDatastoreType} which should be modified
+     * @param path {@link InstanceIdentifier} to read from
+     * @param <D> the data object type
+     * @return the result of the request
+     */
+    public <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean delete(
+            final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
+        boolean result = false;
+        final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
+        transaction.delete(store, path);
+        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+        try {
+            future.checkedGet();
+            result = true;
+        } catch (TransactionCommitFailedException e) {
+            LOG.warn("Failed to delete {} ", path, e);
+        }
+        return result;
+    }
+
+    /**
+     * Executes merge as a blocking transaction.
+     *
+     * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
+     * @param path {@link InstanceIdentifier} for path to read
+     * @param <D> the data object type
+     * @return the result of the request
+     */
+    public <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean merge(
+            final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
+        boolean result = false;
+        final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
+        transaction.merge(logicalDatastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+        try {
+            future.checkedGet();
+            result = true;
+        } catch (TransactionCommitFailedException e) {
+            LOG.warn("Failed to merge {} ", path, e);
+        }
+        return result;
+    }
+}
index c66a71ff06cbc2d6bacfaf8d07ba3e9740521a45..5a0f2b42eea94b5f165142214e7ee7cee230390f 100644 (file)
@@ -1,20 +1,5 @@
 package org.opendaylight.controller.packetcable.provider;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import javax.annotation.concurrent.ThreadSafe;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
@@ -29,6 +14,7 @@ import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.Apps;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.AppsKey;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.Subs;
@@ -42,6 +28,13 @@ import org.pcmm.rcd.IPCMMClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.concurrent.ThreadSafe;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+
 /**
  * Called by ODL framework to start this bundle.
  *
@@ -62,14 +55,11 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
      */
     private DataBroker dataBroker;
 
+    private MdsalUtils mdsalUtils;
+
     private ListenerRegistration<DataChangeListener> ccapDataChangeListenerRegistration;
     private ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration;
 
-    /**
-     * The thread pool executor
-     */
-    private final ExecutorService executor;
-
     // TODO - Revisit these maps and remove the ones no longer necessary
     private final Map<String, Ccaps> ccapMap = new ConcurrentHashMap<>();
     private final Map<String, Gates> gateMap = new ConcurrentHashMap<>();
@@ -88,7 +78,6 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
      */
     public PacketcableProvider() {
         logger.info("Starting provider");
-        executor = Executors.newCachedThreadPool();
     }
 
     @Override
@@ -97,6 +86,8 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
 
         dataBroker =  session.getSALService(DataBroker.class);
 
+        mdsalUtils = new MdsalUtils(dataBroker);
+
         ccapDataChangeListenerRegistration =
                 dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
                         PacketcableProvider.ccapIID, this, DataBroker.DataChangeScope.SUBTREE );
@@ -110,7 +101,6 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
      */
     @Override
     public void close() throws ExecutionException, InterruptedException {
-        executor.shutdown();
         if (ccapDataChangeListenerRegistration != null) {
             ccapDataChangeListenerRegistration.close();
         }
@@ -244,6 +234,8 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
         // remove path for either CCAP or Gates
         public final Set<String> removePathList = new HashSet<>();
 
+        public final Set<InstanceIdentifier<?>> reqCcapIds = new HashSet<>();
+
         public InstanceData(final Map<InstanceIdentifier<?>, DataObject> thisData) {
             // only used to parse createdData or updatedData
             getCcaps(thisData);
@@ -310,9 +302,16 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
         private void getCcaps(final Map<InstanceIdentifier<?>, DataObject> thisData) {
             logger.info("onDataChanged().getCcaps(): " + thisData);
             for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
-                if (entry.getValue() instanceof Ccaps) {
-                    // TODO FIXME - Potential ClassCastException thrown here!!!
-                    ccapIidMap.put((InstanceIdentifier<Ccaps>)entry.getKey(), (Ccaps)entry.getValue());
+
+                if (entry.getKey().getTargetType().equals(Ccaps.class)) {
+                    Ccaps ccaps = ((Ccaps) entry.getValue());
+                    InstanceIdentifier<Ccaps> ccapsIid = InstanceIdentifier.builder(Ccap.class).child(Ccaps.class, new CcapsKey(ccaps.getCcapId())).build();
+                    ccapIidMap.put(ccapsIid, ccaps);
+                }
+
+                if (entry.getKey().getTargetType().equals(Connection.class) ||
+                        entry.getKey().getTargetType().equals(Ccaps.class)) {
+                    reqCcapIds.add(entry.getKey());
                 }
             }
         }
@@ -326,8 +325,31 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
                     // TODO FIXME - Potential ClassCastException thrown here!!!
                     final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
                     getGatePathMap(gateIID);
-                    gateIidMap.put(gateIID, gate);
+                    if (!gateIidMap.containsKey(gateIID)){
+                        gateIidMap.put(gateIID, gate);
+                    }
                 }
+                // TODO reconciliate gates
+//                if (entry.getValue() instanceof Qos) {
+//                    final Qos qos = (Qos) entry.getValue();
+//                    if (qos.getApps() != null) {
+//                        for (Apps apps : qos.getApps()) {
+//                            if (apps.getSubs() != null) {
+//                                for (Subs subs : apps.getSubs()) {
+//                                    if (subs.getGates() != null) {
+//                                        for (Gates gates : subs.getGates()) {
+//                                            final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
+//                                            getGatePathMap(gateIID);
+//                                            if (!gateIidMap.containsKey(gateIID)){
+//                                                gateIidMap.put(gateIID, gates);
+//                                            }
+//                                        }
+//                                    }
+//                                }
+//                            }
+//                        }
+//                    }
+//                }
             }
         }
     }
@@ -338,7 +360,7 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
         // Determine what change action took place by looking at the change object's InstanceIdentifier sets
         // and validate all instance data
         if (!change.getCreatedData().isEmpty()) {
-            if (!new ValidateInstanceData(dataBroker, change.getCreatedData()).validateYang()) {
+            if (!new ValidateInstanceData(mdsalUtils, change.getCreatedData()).validateYang()) {
                 // leave now -- a bad yang object has been detected and a response object has been inserted
                 return;
             }
@@ -346,10 +368,6 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
         } else if (!change.getRemovedPaths().isEmpty()) {
             onRemove(new InstanceData(change.getRemovedPaths()));
         } else if (!change.getUpdatedData().isEmpty()) {
-            if (new ValidateInstanceData(dataBroker, change.getUpdatedData()).isResponseEcho()) {
-                // leave now -- this is an echo of the inserted response object
-                return;
-            }
             onUpdate(new InstanceData(change.getUpdatedData()));
         } else {
             // we should not be here -- complain bitterly and return
@@ -362,7 +380,7 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
 
         // get the CCAP parameters
         String message;
-        if (! thisData.ccapIidMap.isEmpty()) {
+        if (! thisData.reqCcapIds.isEmpty()) {
             for (Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : thisData.ccapIidMap.entrySet()) {
                 final Ccaps thisCcap = entry.getValue();
                 // get the CCAP node identity from the Instance Data
@@ -375,19 +393,20 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
                             final PCMMService pcmmService = new PCMMService(
                                     thisCcap.getAmId().getAmType().shortValue(), thisCcap);
 */
-                    pcmmServiceMap.put(thisCcap.getCcapId(), pcmmService);
                     message = pcmmService.addCcap();
                     if (message.contains("200 OK")) {
+                        pcmmServiceMap.put(thisCcap.getCcapId(), pcmmService);
                         ccapMap.put(ccapId, thisCcap);
                         updateCcapMaps(thisCcap);
                         logger.info("Created CCAP: {}/{} : {}", thisData.gatePath, thisCcap, message);
                         logger.info("Created CCAP: {} : {}", thisData.gatePath, message);
                     } else {
-                        // TODO - when a connection cannot be made, need to remove CCAP from ODL cache.
                         logger.error("Create CCAP Failed: {} : {}", thisData.gatePath, message);
+                        for (final InstanceIdentifier<?> instId : thisData.reqCcapIds) {
+                            mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, instId);
+                        }
+                        ccapMap.remove(ccapId);
                     }
-                    // set the response string in the config ccap object using a new thread
-                    executor.execute(new Response(dataBroker, entry.getKey(), thisCcap, message));
                 } else {
                     logger.error("Already monitoring CCAP - " + thisCcap);
                     break;
@@ -455,8 +474,9 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
                     logger.error("Create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}",
                             gateId, subIdStr, gatePathStr);
                 }
-                // set the response message in the config gate object using a new thread
-                executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+                if (!message.contains("200 OK")) {
+                    mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, entry.getKey());
+                }
             }
         }
     }
@@ -494,23 +514,16 @@ public class PacketcableProvider implements BindingAwareProvider, DataChangeList
             for (final Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : oldData.ccapIidMap.entrySet()) {
                 final Ccaps ccap = entry.getValue();
                 final String ccapId = ccap.getCcapId();
-                String message = String.format("405 Method Not Allowed - %s: CCAP update not permitted (use delete); ",
-                        ccapId);
-                // push new error message onto existing response
-                message += ccap.getResponse();
-                // set the response message in the config object using a new thread -- also restores the original data
-                executor.execute(new Response(dataBroker, entry.getKey(), ccap, message));
+                // restores the original data - although I don't think this is what is done here! I think the update data is put into the DS/config
+                mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, entry.getKey(), ccap);
                 logger.error("onDataChanged(): CCAP update not permitted {}/{}", ccapId, ccap);
             }
         } else {
             for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : oldData.gateIidMap.entrySet()) {
                 final Gates gate = entry.getValue();
                 final String gatePathStr = oldData.gatePath + "/" + gate.getGateId() ;
-                String message = String.format("405 Method Not Allowed - %s: QoS Gate update not permitted (use delete); ", gatePathStr);
-                // push new error message onto existing response
-                message += gate.getResponse();
-                // set the response message in the config object using a new thread -- also restores the original data
-                executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+             // restores the original data - although I don't think this is what is done here! I think the update data is put into the DS/config
+                mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, entry.getKey(), gate);
                 logger.error("onDataChanged(): QoS Gate update not permitted: {}/{}", gatePathStr, gate);
             }
         }
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java
deleted file mode 100644 (file)
index 88132bb..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * The Response object inserts a "response" message object into the given CCAP or Gate object in the
- * config data store.
- *
- * N.B. Updates to the config datastore must be run in a separate thread from the onDataChange() notification.
- * Therefore, the Response object must always be invoked via executor.execute(resonse) after it is
- * configured during new Response(dataBroker, ccapIID, ccapbase, message) for example.
- *
- * Also note well that when a CCAP or Gate object is updated with this "response" message, it will trigger
- * another recursive onDataChange() notification seen in the change.getUpdatedData() -- this update must be ignored.
- */
-package org.opendaylight.controller.packetcable.provider;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Response implements Runnable {
-
-       private Logger logger = LoggerFactory.getLogger(Response.class);
-       private DataBroker dataBroker;
-       private String message = null;
-       private InstanceIdentifier<Ccaps> ccapIID = null;
-       private Ccaps ccapBase = null;
-       private InstanceIdentifier<Gates> gateIID = null;
-       private Gates gateBase = null;
-
-       public Response(DataBroker dataBroker, InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
-               this.dataBroker = dataBroker;
-               this.ccapIID = ccapIID;
-               this.ccapBase = ccapBase;
-               this.message = message;
-       }
-       public Response(DataBroker dataBroker, InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
-               this.dataBroker = dataBroker;
-               this.gateIID = gateIID;
-               this.gateBase = gateBase;
-               this.message = message;
-       }
-
-       public String getMessage() {
-               return message;
-       }
-       public void setMessage(String message) {
-               this.message = message;
-       }
-       public void addMessage(String message) {
-               this.message += message;
-       }
-       public InstanceIdentifier<Ccaps> getCcapIID() {
-               return ccapIID;
-       }
-       public void setCcapIID(InstanceIdentifier<Ccaps> ccapIID) {
-               this.ccapIID = ccapIID;
-       }
-       public Ccaps getCcapBase() {
-               return ccapBase;
-       }
-       public void setCcapBase(Ccaps ccapBase) {
-               this.ccapBase = ccapBase;
-       }
-       public InstanceIdentifier<Gates> getGateIID() {
-               return gateIID;
-       }
-       public void setGateIID(InstanceIdentifier<Gates> gateIID) {
-               this.gateIID = gateIID;
-       }
-       public Gates getGateBase() {
-               return gateBase;
-       }
-       public void setGateBase(Gates gateBase) {
-               this.gateBase = gateBase;
-       }
-
-       @SuppressWarnings("deprecation")
-       public void setResponse(InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
-               CcapsBuilder ccapBuilder = new CcapsBuilder(ccapBase);
-               ccapBuilder.setResponse(message);
-               Ccaps ccap = ccapBuilder.build();
-        WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-        writeTx.merge(LogicalDatastoreType.CONFIGURATION, ccapIID, ccap, true);
-        writeTx.commit();
-        logger.debug("Response.setResponse(ccap) complete {} {} {}", message, ccap, ccapIID);
-       }
-       @SuppressWarnings("deprecation")
-       public void setResponse(InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
-               GatesBuilder gateBuilder = new GatesBuilder(gateBase);
-               gateBuilder.setResponse(message);
-               Gates gate = gateBuilder.build();
-        WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-        writeTx.merge(LogicalDatastoreType.CONFIGURATION, gateIID, gate, true);
-        writeTx.commit();
-        logger.debug("Response.setResponse(gate) complete: {} {} {}", message, gate, gateIID);
-       }
-
-       @Override
-       public void run() {
-               if (ccapIID != null) {
-                       setResponse(ccapIID, ccapBase, message);
-               } else if (gateIID != null) {
-                       setResponse(gateIID, gateBase, message);
-               } else {
-                       logger.error("Unknown Response: must be for a CCAP or Gate instance");
-               }
-       }
-}
-
index 4822881f25019f44f328282052c58cdfdb722679..b930d6cca5b781b46458601741de969305dfb4d6 100644 (file)
  */
 package org.opendaylight.controller.packetcable.provider;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
@@ -39,933 +48,905 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 public class ValidateInstanceData {
 
-       private final static Logger logger = LoggerFactory.getLogger(ValidateInstanceData.class);
+    private final static Logger logger = LoggerFactory.getLogger(ValidateInstanceData.class);
+
+    // Final members
+    private final MdsalUtils mdsalUtils;
 
-       // Final members
-       private final DataBroker dataBroker;
-       private final ExecutorService executor;
+    // Gate Identities
+    private final Map<InstanceIdentifier<Gates>, Gates> gateIidMap;
 
-       // Gate Identities
-       private final Map<InstanceIdentifier<Gates>, Gates> gateIidMap;
+    // CCAP Identity
+    private transient Ccaps ccap;
+    private transient InstanceIdentifier<Ccaps> ccapIID;
 
-       // CCAP Identity
-       private transient Ccaps ccap;
-       private transient InstanceIdentifier<Ccaps> ccapIID;
+    public ValidateInstanceData(final MdsalUtils mdsalUtils, final Map<InstanceIdentifier<?>, DataObject> thisData) {
+        this.mdsalUtils = mdsalUtils;
+        getCcap(thisData);
 
-       public ValidateInstanceData(final DataBroker dataBroker, final Map<InstanceIdentifier<?>, DataObject> thisData) {
-               executor = Executors.newCachedThreadPool();
-               this.dataBroker = dataBroker;
-               getCcap(thisData);
+        // Must be instantiated prior to retreiving the gates below
+        gateIidMap = new ConcurrentHashMap<>();
 
-               // Must be instantiated prior to retreiving the gates below
-               gateIidMap = new ConcurrentHashMap<>();
+        // TODO FIXME - this value is always null???
+        if (ccap == null) {
+            getGates(thisData);
+        }
+    }
 
-               // TODO FIXME - this value is always null???
-               if (ccap == null) {
-                       getGates(thisData);
-               }
-       }
-       public boolean isResponseEcho() {
-               // see if there is a response object in the updated data
-               // if so this is an echo of the response message insertion so our caller can exit right away
-               if (ccap != null && ccap.getResponse() != null) {
-                       return true;
-               } else if (! gateIidMap.isEmpty() && gateIidMap.values().iterator().next().getResponse() != null) {
-                       return true;
-               }
-               return false;
-       }
-       public boolean validateYang() {
-               final String badText = "400 Bad Request - Invalid Element Values in json object - ";
-               if (isResponseEcho()) {
-                       // don't validiate the echo again
-                       return true;
-               }
-               if (ccap != null) {
-                       Response response = new Response(dataBroker, ccapIID, ccap, badText);
-                       if (! validateCcap(ccap, response)) {
-                               logger.error("Validate CCAP {} failed - {}", ccap.getCcapId(), response.getMessage());
-                               executor.execute(response);
-                               return false;
-                       }
-               } else if (! gateIidMap.isEmpty()) {
-                       for (Map.Entry<InstanceIdentifier<Gates>, Gates> entry : gateIidMap.entrySet()) {
-                               InstanceIdentifier<Gates> gateIID = entry.getKey();
-                               Gates gate = entry.getValue();
-                               Response response = new Response(dataBroker, gateIID, gate, badText);
-                               if (! validateGate(gate, response)) {
-                                       logger.error("Validate Gate {} failed - {}", gate.getGateId(), response.getMessage());
-                                       executor.execute(response);
-                                       return false;
-                               }
-                       }
-               }
-               return true;
-       }
+    public boolean validateYang() {
+        if (ccap != null) {
+            if (! validateCcap(ccap)) {
+                logger.error("Validate CCAP {} failed - {}", ccap.getCcapId());
+                mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, ccapIID);
+                return false;
+            }
+        } else if (! gateIidMap.isEmpty()) {
+            for (Map.Entry<InstanceIdentifier<Gates>, Gates> entry : gateIidMap.entrySet()) {
+                InstanceIdentifier<Gates> gateIID = entry.getKey();
+                Gates gate = entry.getValue();
+                if (! validateGate(gate)) {
+                    logger.error("Validate Gate {} failed - {}", gate.getGateId());
+                    mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, gateIID);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
 
-       private void getCcap(final Map<InstanceIdentifier<?>, DataObject> thisData) {
-               for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
-                       if (entry.getValue() instanceof Ccaps) {
-                   ccap = (Ccaps)entry.getValue();
-                               // TODO FIXME - ClassCastException waiting to occur here!!!
-                   ccapIID = (InstanceIdentifier<Ccaps>) entry.getKey();
-               }
-           }
-       }
+    private void getCcap(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+        for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+            if (entry.getValue() instanceof Ccaps) {
+                ccap = (Ccaps)entry.getValue();
+                // TODO FIXME - ClassCastException waiting to occur here!!!
+                ccapIID = (InstanceIdentifier<Ccaps>) entry.getKey();
+            }
+        }
+    }
 
-       private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
-               for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
-                       if (entry.getValue() instanceof Gates) {
-                               final Gates gate = (Gates)entry.getValue();
-                               // TODO FIXME - ClassCastException waiting to occur here!!!
-                               final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
-                               gateIidMap.put(gateIID, gate);
-                       }
-           }
-       }
-       private String validateMethod(final Class<?> thisClass, final Object thisObj, final String methodName) {
-               try {
-                       final Method method = thisClass.getMethod(methodName);
-                       method.invoke(thisObj);
-               } catch (IllegalArgumentException e) {
-                       return e.getMessage();
-               } catch (Exception e) {
-                       return " ";
-//                     error = String.format("%s.%s(): Method failed: %s ", thisClass.getSimpleName(), methodName, e.getMessage());
-               }
-               return null;
-       }
+    private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+        for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+            if (entry.getValue() instanceof Gates) {
+                final Gates gate = (Gates)entry.getValue();
+                // TODO FIXME - ClassCastException waiting to occur here!!!
+                final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
+                gateIidMap.put(gateIID, gate);
+            }
+        }
+    }
+    private String validateMethod(final Class<?> thisClass, final Object thisObj, final String methodName) {
+        try {
+            final Method method = thisClass.getMethod(methodName);
+            method.invoke(thisObj);
+        } catch (IllegalArgumentException e) {
+            return e.getMessage();
+        } catch (Exception e) {
+            return " ";
+//          error = String.format("%s.%s(): Method failed: %s ", thisClass.getSimpleName(), methodName, e.getMessage());
+        }
+        return null;
+    }
 
-       private boolean validateGateSpec(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
-               // gate-spec
-               String message = "";
-               String error;
-               boolean valid = true;
-               GateSpec gateSpec = gate.getGateSpec();
-               if (gateSpec != null) {
-                       final ServiceFlowDirection dir;
-                       error = validateMethod(GateSpec.class, gateSpec, "getDirection");
-                       if (error == null) {
-                               dir = gateSpec.getDirection();
-                               if (dir != null) {
-                                       if (gate.getTrafficProfile().getServiceClassName() != null) {
-                                               message += " gate-spec.direction not allowed for traffic-profile.SCN;";
-                                               valid = false;
-                                       }
-                               }
-                       } else {
-                               message += " gate-spec.direction invalid: must be 'us' or 'ds' -" + error;
-                               dir = null;
-                               valid = false;
-                       }
-                       final TosByte tosByte;
-                       error = validateMethod(GateSpec.class, gateSpec, "getDscpTosOverwrite");
-                       if (error == null) {
-                               tosByte = gateSpec.getDscpTosOverwrite();
-                       } else {
-                               message += " gate-spec.dscp-tos-overwrite invalid: " + error;
-                               tosByte = null;
-                               valid = false;
-                       }
-                       final TosByte tosMask;
-                       error = validateMethod(GateSpec.class, gateSpec, "getDscpTosMask");
-                       if (error == null) {
-                               tosMask = gateSpec.getDscpTosMask();
-                               if (tosByte != null && tosMask == null) {
-                                       message += " gate-spec.dscp-tos-mask missing;";
-                                       valid = false;
-                               }
-                       } else {
-                               message += " gate-spec.dscp-tos-mask invalid: " + error;
-                               tosMask = null;
-                               valid = false;
-                       }
-                       if (! valid) {
-                               // rebuild the gateSpec with nulls replacing bad values
-                               final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
-                               gateSpecBuilder.setDirection(dir);
-                               gateSpecBuilder.setDscpTosOverwrite(tosByte);
-                               gateSpecBuilder.setDscpTosMask(tosMask);
-                               gateSpec = gateSpecBuilder.build();
-                               // update the gate
-                               gateBuilder.setGateSpec(gateSpec);
-                       }
-               }
-               if (! valid) {
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateGateSpec(final Gates gate, final GatesBuilder gateBuilder) {
+        // gate-spec
+        String message = "";
+        String error;
+        boolean valid = true;
+        GateSpec gateSpec = gate.getGateSpec();
+        if (gateSpec != null) {
+            final ServiceFlowDirection dir;
+            error = validateMethod(GateSpec.class, gateSpec, "getDirection");
+            if (error == null) {
+                dir = gateSpec.getDirection();
+                if (dir != null) {
+                    if (gate.getTrafficProfile().getServiceClassName() != null) {
+                        message += " gate-spec.direction not allowed for traffic-profile.SCN;";
+                        valid = false;
+                    }
+                }
+            } else {
+                message += " gate-spec.direction invalid: must be 'us' or 'ds' -" + error;
+                dir = null;
+                valid = false;
+            }
+            final TosByte tosByte;
+            error = validateMethod(GateSpec.class, gateSpec, "getDscpTosOverwrite");
+            if (error == null) {
+                tosByte = gateSpec.getDscpTosOverwrite();
+            } else {
+                message += " gate-spec.dscp-tos-overwrite invalid: " + error;
+                tosByte = null;
+                valid = false;
+            }
+            final TosByte tosMask;
+            error = validateMethod(GateSpec.class, gateSpec, "getDscpTosMask");
+            if (error == null) {
+                tosMask = gateSpec.getDscpTosMask();
+                if (tosByte != null && tosMask == null) {
+                    message += " gate-spec.dscp-tos-mask missing;";
+                    valid = false;
+                }
+            } else {
+                message += " gate-spec.dscp-tos-mask invalid: " + error;
+                tosMask = null;
+                valid = false;
+            }
+            if (! valid) {
+                // rebuild the gateSpec with nulls replacing bad values
+                final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
+                gateSpecBuilder.setDirection(dir);
+                gateSpecBuilder.setDscpTosOverwrite(tosByte);
+                gateSpecBuilder.setDscpTosMask(tosMask);
+                gateSpec = gateSpecBuilder.build();
+                // update the gate
+                gateBuilder.setGateSpec(gateSpec);
+            }
+        }
+        if (! valid) {
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       private boolean validateTrafficProfile(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
-               // traffic-profile
-               String message = "";
-               boolean valid = true;
-               TrafficProfile profile = gate.getTrafficProfile();
-               if (profile == null) {
-                       message += " traffic-profile is required;";
-                       valid = false;
-               } else {
-                       final ServiceClassName scn;
-                       final String error = validateMethod(TrafficProfile.class, profile, "getServiceClassName");
-                       if (error == null) {
-                               scn = profile.getServiceClassName();
-                               if (scn == null) {
-                                       message += " traffic-profile.service-class-name missing;";
-                                       valid = false;
-                               }
-                       } else {
-                               message += " traffic-profile.service-class-name invalid: must be 2-16 characters " + error;
-                               scn = null;
-                               valid = false;
-                       }
-                       if (! valid) {
-                               final TrafficProfileBuilder profileBuilder = new TrafficProfileBuilder();
-                               // TODO FIXME - scn is always null???
-                               profileBuilder.setServiceClassName(scn);
-                               profile = profileBuilder.build();
-                               // update the gate
-                               gateBuilder.setTrafficProfile(profile);
-                       }
-               }
-               if (! valid) {
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateTrafficProfile(final Gates gate, final GatesBuilder gateBuilder) {
+        // traffic-profile
+        String message = "";
+        boolean valid = true;
+        TrafficProfile profile = gate.getTrafficProfile();
+        if (profile == null) {
+            message += " traffic-profile is required;";
+            valid = false;
+        } else {
+            final ServiceClassName scn;
+            final String error = validateMethod(TrafficProfile.class, profile, "getServiceClassName");
+            if (error == null) {
+                scn = profile.getServiceClassName();
+                if (scn == null) {
+                    message += " traffic-profile.service-class-name missing;";
+                    valid = false;
+                }
+            } else {
+                message += " traffic-profile.service-class-name invalid: must be 2-16 characters " + error;
+                scn = null;
+                valid = false;
+            }
+            if (! valid) {
+                final TrafficProfileBuilder profileBuilder = new TrafficProfileBuilder();
+                // TODO FIXME - scn is always null???
+                profileBuilder.setServiceClassName(scn);
+                profile = profileBuilder.build();
+                // update the gate
+                gateBuilder.setTrafficProfile(profile);
+            }
+        }
+        if (! valid) {
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       // TODO FIXME - Break this method apart
-       private boolean validateClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
-               // validate classifier
-               String message = "";
-               boolean valid = true;
-               int count = 0;
-               Classifier classifier = gate.getClassifier();
-               // SIP
-               final Ipv4Address sip;
-               String error = validateMethod(Classifier.class, classifier, "getSrcIp");
-               if (error == null) {
-                       sip = classifier.getSrcIp();
-                       count++;
-               } else {
-                       message += " classifier.srcIp invalid: - " + error;
-                       sip = null;
-                       valid = false;
-               }
-               // DIP
-               final Ipv4Address dip;
-               error = validateMethod(Classifier.class, classifier, "getDstIp");
-               if (error == null) {
-                       dip = classifier.getDstIp();
-                       count++;
-               } else {
-                       message += " classifier.dstIp invalid: - " + error;
-                       dip = null;
-                       valid = false;
-               }
-               // Protocol
-               final TpProtocol proto;
-               error = validateMethod(Classifier.class, classifier, "getProtocol");
-               if (error == null) {
-                       proto = classifier.getProtocol();
-                       count++;
-               } else {
-                       message += " classifier.protocol invalid: - " + error;
-                       proto = null;
-                       valid = false;
-               }
-               // Source Port
-               final PortNumber sport;
-               error = validateMethod(Classifier.class, classifier, "getSrcPort");
-               if (error == null) {
-                       sport = classifier.getSrcPort();
-                       count++;
-               } else {
-                       message += " classifier.srcPort invalid: - " + error;
-                       sport = null;
-                       valid = false;
-               }
-               // Destination Port
-               final PortNumber dport;
-               error = validateMethod(Classifier.class, classifier, "getDstPort");
-               if (error == null) {
-                       dport = classifier.getDstPort();
-                       count++;
-               } else {
-                       message += " classifier.dstPort invalid: - " + error;
-                       dport = null;
-                       valid = false;
-               }
-               // TOS
-               final TosByte tosByte;
-               error = validateMethod(Classifier.class, classifier, "getTosByte");
-               if (error == null) {
-                       tosByte = classifier.getTosByte();
-                       count++;
-               } else {
-                       message += " classifier.tosByte invalid: " + error;
-                       tosByte = null;
-                       valid = false;
-               }
-               final TosByte tosMask;
-               error = validateMethod(Classifier.class, classifier, "getTosMask");
-               if (error == null) {
-                       tosMask = classifier.getTosMask();
-                       if (tosByte != null && tosMask == null) {
-                               message += " classifier.tosMask missing;";
-                               valid = false;
-                       }
-               } else {
-                       message += " classifier.tosMask invalid: " + error;
-                       tosMask = null;
-                       valid = false;
-               }
-               if (count == 0) {
-                       message += " classifer must have at least one match field";
-                       valid = false;
-               }
-               if (! valid) {
-                       final ClassifierBuilder cBuilder = new ClassifierBuilder();
-                       cBuilder.setSrcIp(sip);
-                       cBuilder.setDstIp(dip);
-                       cBuilder.setProtocol(proto);
-                       cBuilder.setSrcPort(sport);
-                       cBuilder.setDstPort(dport);
-                       cBuilder.setTosByte(tosByte);
-                       cBuilder.setTosMask(tosMask);
-                       classifier = cBuilder.build();
-                       gateBuilder.setClassifier(classifier);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    // TODO FIXME - Break this method apart
+    private boolean validateClassifier(final Gates gate, final GatesBuilder gateBuilder) {
+        // validate classifier
+        String message = "";
+        boolean valid = true;
+        int count = 0;
+        Classifier classifier = gate.getClassifier();
+        // SIP
+        final Ipv4Address sip;
+        String error = validateMethod(Classifier.class, classifier, "getSrcIp");
+        if (error == null) {
+            sip = classifier.getSrcIp();
+            count++;
+        } else {
+            message += " classifier.srcIp invalid: - " + error;
+            sip = null;
+            valid = false;
+        }
+        // DIP
+        final Ipv4Address dip;
+        error = validateMethod(Classifier.class, classifier, "getDstIp");
+        if (error == null) {
+            dip = classifier.getDstIp();
+            count++;
+        } else {
+            message += " classifier.dstIp invalid: - " + error;
+            dip = null;
+            valid = false;
+        }
+        // Protocol
+        final TpProtocol proto;
+        error = validateMethod(Classifier.class, classifier, "getProtocol");
+        if (error == null) {
+            proto = classifier.getProtocol();
+            count++;
+        } else {
+            message += " classifier.protocol invalid: - " + error;
+            proto = null;
+            valid = false;
+        }
+        // Source Port
+        final PortNumber sport;
+        error = validateMethod(Classifier.class, classifier, "getSrcPort");
+        if (error == null) {
+            sport = classifier.getSrcPort();
+            count++;
+        } else {
+            message += " classifier.srcPort invalid: - " + error;
+            sport = null;
+            valid = false;
+        }
+        // Destination Port
+        final PortNumber dport;
+        error = validateMethod(Classifier.class, classifier, "getDstPort");
+        if (error == null) {
+            dport = classifier.getDstPort();
+            count++;
+        } else {
+            message += " classifier.dstPort invalid: - " + error;
+            dport = null;
+            valid = false;
+        }
+        // TOS
+        final TosByte tosByte;
+        error = validateMethod(Classifier.class, classifier, "getTosByte");
+        if (error == null) {
+            tosByte = classifier.getTosByte();
+            count++;
+        } else {
+            message += " classifier.tosByte invalid: " + error;
+            tosByte = null;
+            valid = false;
+        }
+        final TosByte tosMask;
+        error = validateMethod(Classifier.class, classifier, "getTosMask");
+        if (error == null) {
+            tosMask = classifier.getTosMask();
+            if (tosByte != null && tosMask == null) {
+                message += " classifier.tosMask missing;";
+                valid = false;
+            }
+        } else {
+            message += " classifier.tosMask invalid: " + error;
+            tosMask = null;
+            valid = false;
+        }
+        if (count == 0) {
+            message += " classifer must have at least one match field";
+            valid = false;
+        }
+        if (! valid) {
+            final ClassifierBuilder cBuilder = new ClassifierBuilder();
+            cBuilder.setSrcIp(sip);
+            cBuilder.setDstIp(dip);
+            cBuilder.setProtocol(proto);
+            cBuilder.setSrcPort(sport);
+            cBuilder.setDstPort(dport);
+            cBuilder.setTosByte(tosByte);
+            cBuilder.setTosMask(tosMask);
+            classifier = cBuilder.build();
+            gateBuilder.setClassifier(classifier);
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       // TODO FIXME - breakup this method
-       private boolean validateExtClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
-               // validate ext-classifier
-               String message = "";
-               String error;
-               boolean valid = true;
-               int count = 0;
-               ExtClassifier extClassifier = gate.getExtClassifier();
-               // SIP & mask
-               final Ipv4Address sip;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIp");
-               if (error == null) {
-                       sip = extClassifier.getSrcIp();
-                       count++;
-               } else {
-                       message += " ext-classifier.srcIp invalid: - " + error;
-                       sip = null;
-                       valid = false;
-               }
-               final Ipv4Address sipMask;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIpMask");
-               if (error == null) {
-                       sipMask = extClassifier.getSrcIpMask();
-                       count++;
-               } else {
-                       message += " ext-classifier.srcIpMask invalid: - " + error;
-                       sipMask = null;
-                       valid = false;
-               }
-               if (sip != null && sipMask == null) {
-                       message += " ext-classifier.srcIpMask missing";
-                       valid = false;
-               }
-               // DIP & mask
-               final Ipv4Address dip;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getDstIp");
-               if (error == null) {
-                       dip = extClassifier.getDstIp();
-                       count++;
-               } else {
-                       message += " ext-classifier.dstIp invalid: - " + error;
-                       dip = null;
-                       valid = false;
-               }
-               final Ipv4Address dipMask;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getDstIpMask");
-               if (error == null) {
-                       dipMask = extClassifier.getDstIpMask();
-                       count++;
-               } else {
-                       message += " ext-classifier.srcIpMask invalid: - " + error;
-                       dipMask = null;
-                       valid = false;
-               }
-               if (dip != null && dipMask == null) {
-                       message += " ext-classifier.dstIpMask missing;";
-                       valid = false;
-               }
-               // Protocol
-               final TpProtocol proto;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getProtocol");
-               if (error == null) {
-                       proto = extClassifier.getProtocol();
-                       count++;
-               } else {
-                       message += " ext-classifier.protocol invalid: - " + error;
-                       proto = null;
-                       valid = false;
-               }
-               // Source port range
-               final PortNumber sportStart;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortStart");
-               if (error == null) {
-                       sportStart = extClassifier.getSrcPortStart();
-                       count++;
-               } else {
-                       message += " ext-classifier.srcPortStart invalid: - " + error;
-                       sportStart = null;
-                       valid = false;
-               }
-               final PortNumber sportEnd;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortEnd");
-               if (error == null) {
-                       sportEnd = extClassifier.getSrcPortEnd();
-                       count++;
-               } else {
-                       message += " ext-classifier.srcPortEnd invalid: - " + error;
-                       sportEnd = null;
-                       valid = false;
-               }
-               if (sportStart != null && sportEnd != null) {
-                       if (sportStart.getValue() > sportEnd.getValue()) {
-                               message += " ext-classifier.srcPortStart greater than srcPortEnd";
-                               valid = false;
-                       }
-               }
-               // Destination port range
-               final PortNumber dportStart;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortStart");
-               if (error == null) {
-                       dportStart = extClassifier.getDstPortStart();
-                       count++;
-               } else {
-                       message += " ext-classifier.dstPortStart invalid: - " + error;
-                       dportStart = null;
-                       valid = false;
-               }
-               final PortNumber dportEnd;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortEnd");
-               if (error == null) {
-                       dportEnd = extClassifier.getDstPortEnd();
-                       count++;
-               } else {
-                       message += " ext-classifier.dstPortEnd invalid: - " + error;
-                       dportEnd = null;
-                       valid = false;
-               }
-               if (dportStart != null && dportEnd != null) {
-                       if (dportStart.getValue() > dportEnd.getValue()) {
-                               message += " ext-classifier.dstPortStart greater than dstPortEnd";
-                               valid = false;
-                       }
-               }
-               // TOS byte
-               final TosByte tosByte;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getTosByte");
-               if (error == null) {
-                       tosByte = extClassifier.getTosByte();
-                       count++;
-               } else {
-                       message += " ext-classifier.tosByte invalid: " + error;
-                       tosByte = null;
-                       valid = false;
-               }
-               final TosByte tosMask;
-               error = validateMethod(ExtClassifier.class, extClassifier, "getTosMask");
-               if (error == null) {
-                       tosMask = extClassifier.getTosMask();
-                       if (tosByte != null && tosMask == null) {
-                               message += " ext-classifier.tosMask missing;";
-                               valid = false;
-                       }
-               } else {
-                       message += " ext-classifier.tosMask invalid: " + error;
-                       tosMask = null;
-                       valid = false;
-               }
-               if (count == 0) {
-                       message += " ext-classifer must have at least one match field";
-                       valid = false;
-               }
-               if (! valid) {
-                       final ExtClassifierBuilder cBuilder = new ExtClassifierBuilder();
-                       cBuilder.setSrcIp(sip);
-                       cBuilder.setSrcIpMask(sipMask);
-                       cBuilder.setDstIp(dip);
-                       cBuilder.setDstIpMask(dipMask);
-                       cBuilder.setProtocol(proto);
-                       cBuilder.setSrcPortStart(sportStart);
-                       cBuilder.setSrcPortEnd(sportEnd);
-                       cBuilder.setDstPortStart(dportStart);
-                       cBuilder.setDstPortEnd(dportEnd);
-                       cBuilder.setTosByte(tosByte);
-                       cBuilder.setTosMask(tosMask);
-                       extClassifier = cBuilder.build();
-                       gateBuilder.setExtClassifier(extClassifier);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    // TODO FIXME - breakup this method
+    private boolean validateExtClassifier(final Gates gate, final GatesBuilder gateBuilder) {
+        // validate ext-classifier
+        String message = "";
+        String error;
+        boolean valid = true;
+        int count = 0;
+        ExtClassifier extClassifier = gate.getExtClassifier();
+        // SIP & mask
+        final Ipv4Address sip;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIp");
+        if (error == null) {
+            sip = extClassifier.getSrcIp();
+            count++;
+        } else {
+            message += " ext-classifier.srcIp invalid: - " + error;
+            sip = null;
+            valid = false;
+        }
+        final Ipv4Address sipMask;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIpMask");
+        if (error == null) {
+            sipMask = extClassifier.getSrcIpMask();
+            count++;
+        } else {
+            message += " ext-classifier.srcIpMask invalid: - " + error;
+            sipMask = null;
+            valid = false;
+        }
+        if (sip != null && sipMask == null) {
+            message += " ext-classifier.srcIpMask missing";
+            valid = false;
+        }
+        // DIP & mask
+        final Ipv4Address dip;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getDstIp");
+        if (error == null) {
+            dip = extClassifier.getDstIp();
+            count++;
+        } else {
+            message += " ext-classifier.dstIp invalid: - " + error;
+            dip = null;
+            valid = false;
+        }
+        final Ipv4Address dipMask;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getDstIpMask");
+        if (error == null) {
+            dipMask = extClassifier.getDstIpMask();
+            count++;
+        } else {
+            message += " ext-classifier.srcIpMask invalid: - " + error;
+            dipMask = null;
+            valid = false;
+        }
+        if (dip != null && dipMask == null) {
+            message += " ext-classifier.dstIpMask missing;";
+            valid = false;
+        }
+        // Protocol
+        final TpProtocol proto;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getProtocol");
+        if (error == null) {
+            proto = extClassifier.getProtocol();
+            count++;
+        } else {
+            message += " ext-classifier.protocol invalid: - " + error;
+            proto = null;
+            valid = false;
+        }
+        // Source port range
+        final PortNumber sportStart;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortStart");
+        if (error == null) {
+            sportStart = extClassifier.getSrcPortStart();
+            count++;
+        } else {
+            message += " ext-classifier.srcPortStart invalid: - " + error;
+            sportStart = null;
+            valid = false;
+        }
+        final PortNumber sportEnd;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortEnd");
+        if (error == null) {
+            sportEnd = extClassifier.getSrcPortEnd();
+            count++;
+        } else {
+            message += " ext-classifier.srcPortEnd invalid: - " + error;
+            sportEnd = null;
+            valid = false;
+        }
+        if (sportStart != null && sportEnd != null) {
+            if (sportStart.getValue() > sportEnd.getValue()) {
+                message += " ext-classifier.srcPortStart greater than srcPortEnd";
+                valid = false;
+            }
+        }
+        // Destination port range
+        final PortNumber dportStart;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortStart");
+        if (error == null) {
+            dportStart = extClassifier.getDstPortStart();
+            count++;
+        } else {
+            message += " ext-classifier.dstPortStart invalid: - " + error;
+            dportStart = null;
+            valid = false;
+        }
+        final PortNumber dportEnd;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortEnd");
+        if (error == null) {
+            dportEnd = extClassifier.getDstPortEnd();
+            count++;
+        } else {
+            message += " ext-classifier.dstPortEnd invalid: - " + error;
+            dportEnd = null;
+            valid = false;
+        }
+        if (dportStart != null && dportEnd != null) {
+            if (dportStart.getValue() > dportEnd.getValue()) {
+                message += " ext-classifier.dstPortStart greater than dstPortEnd";
+                valid = false;
+            }
+        }
+        // TOS byte
+        final TosByte tosByte;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getTosByte");
+        if (error == null) {
+            tosByte = extClassifier.getTosByte();
+            count++;
+        } else {
+            message += " ext-classifier.tosByte invalid: " + error;
+            tosByte = null;
+            valid = false;
+        }
+        final TosByte tosMask;
+        error = validateMethod(ExtClassifier.class, extClassifier, "getTosMask");
+        if (error == null) {
+            tosMask = extClassifier.getTosMask();
+            if (tosByte != null && tosMask == null) {
+                message += " ext-classifier.tosMask missing;";
+                valid = false;
+            }
+        } else {
+            message += " ext-classifier.tosMask invalid: " + error;
+            tosMask = null;
+            valid = false;
+        }
+        if (count == 0) {
+            message += " ext-classifer must have at least one match field";
+            valid = false;
+        }
+        if (! valid) {
+            final ExtClassifierBuilder cBuilder = new ExtClassifierBuilder();
+            cBuilder.setSrcIp(sip);
+            cBuilder.setSrcIpMask(sipMask);
+            cBuilder.setDstIp(dip);
+            cBuilder.setDstIpMask(dipMask);
+            cBuilder.setProtocol(proto);
+            cBuilder.setSrcPortStart(sportStart);
+            cBuilder.setSrcPortEnd(sportEnd);
+            cBuilder.setDstPortStart(dportStart);
+            cBuilder.setDstPortEnd(dportEnd);
+            cBuilder.setTosByte(tosByte);
+            cBuilder.setTosMask(tosMask);
+            extClassifier = cBuilder.build();
+            gateBuilder.setExtClassifier(extClassifier);
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       // TODO FIXME - break apart this method.
-       private boolean validateIpv6Classifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
-               // validate ipv6-classifier
-               String message = "";
-               String error;
-               boolean valid = true;
-               int count = 0;
-               Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
-               // Source IPv6 prefix
-               final Ipv6Prefix sip6;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcIp6");
-               if (error == null) {
-                       sip6 = ipv6Classifier.getSrcIp6();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.srcIp invalid: - " + error;
-                       sip6 = null;
-                       valid = false;
-               }
-               // Destination IPv6 prefix
-               final Ipv6Prefix dip6;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstIp6");
-               if (error == null) {
-                       dip6 = ipv6Classifier.getDstIp6();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.dstIp invalid: - " + error;
-                       dip6 = null;
-                       valid = false;
-               }
-               // Flow label
-               Long flowLabel;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getFlowLabel");
-               if (error == null) {
-                       flowLabel = ipv6Classifier.getFlowLabel();
-                       if (flowLabel > 1048575) {
-                               message += " ipv6-classifier.flowLabel invalid: - must be 0..1048575";
-                               flowLabel = null;
-                               valid = false;
-                       } else {
-                               count++;
-                       }
-               } else {
-                       message += " ipv6-classifier.flowLabel invalid: - " + error;
-                       flowLabel = null;
-                       valid = false;
-               }
-               // Next Hdr
-               final TpProtocol nxtHdr;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getNextHdr");
-               if (error == null) {
-                       nxtHdr = ipv6Classifier.getNextHdr();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.nextHdr invalid: - " + error;
-                       nxtHdr = null;
-                       valid = false;
-               }
-               // Source port range
-               final PortNumber sportStart;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortStart");
-               if (error == null) {
-                       sportStart = ipv6Classifier.getSrcPortStart();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.srcPortStart invalid: - " + error;
-                       sportStart = null;
-                       valid = false;
-               }
-               final PortNumber sportEnd;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortEnd");
-               if (error == null) {
-                       sportEnd = ipv6Classifier.getSrcPortEnd();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.srcPortEnd invalid: - " + error;
-                       sportEnd = null;
-                       valid = false;
-               }
-               if (sportStart != null && sportEnd != null) {
-                       if (sportStart.getValue() > sportEnd.getValue()) {
-                               message += " ipv6-classifier.srcPortStart greater than srcPortEnd";
-                               valid = false;
-                       }
-               }
-               // Destination port range
-               final PortNumber dportStart;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortStart");
-               if (error == null) {
-                       dportStart = ipv6Classifier.getDstPortStart();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.dstPortStart invalid: - " + error;
-                       dportStart = null;
-                       valid = false;
-               }
-               final PortNumber dportEnd;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortEnd");
-               if (error == null) {
-                       dportEnd = ipv6Classifier.getDstPortEnd();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.dstPortEnd invalid: - " + error;
-                       dportEnd = null;
-                       valid = false;
-               }
-               if (dportStart != null && dportEnd != null) {
-                       if (dportStart.getValue() > dportEnd.getValue()) {
-                               message += " ipv6-classifier.dstPortStart greater than dstPortEnd";
-                               valid = false;
-                       }
-               }
-               // TC byte
-               final TosByte tcLow;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcLow");
-               if (error == null) {
-                       tcLow = ipv6Classifier.getTcLow();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.tc-low invalid: " + error;
-                       tcLow = null;
-                       valid = false;
-               }
-               final TosByte tcHigh;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcHigh");
-               if (error == null) {
-                       tcHigh = ipv6Classifier.getTcHigh();
-                       count++;
-               } else {
-                       message += " ipv6-classifier.tc-high invalid: " + error;
-                       tcHigh = null;
-                       valid = false;
-               }
-               if (tcLow != null && tcHigh != null) {
-                       if (tcLow.getValue() > tcHigh.getValue()) {
-                               message += " ipv6-classifier.tc-low is greater than tc-high";
-                               valid = false;
-                       }
-               }
-               final TosByte tcMask;
-               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcMask");
-               if (error == null) {
-                       tcMask = ipv6Classifier.getTcMask();
-               } else {
-                       message += " ipv6-classifier.tc-mask invalid: " + error;
-                       tcMask = null;
-                       valid = false;
-               }
-               if (tcLow != null && tcHigh != null && tcMask == null) {
-                       message += " ipv6-classifier.tc-mask missing;";
-                       valid = false;
-               }
-               if (count == 0) {
-                       message += " ipv6-classifer must have at least one match field";
-                       valid = false;
-               }
-               // rebuild ?
-               if (! valid) {
-                       final Ipv6ClassifierBuilder cBuilder = new Ipv6ClassifierBuilder();
-                       cBuilder.setSrcIp6(sip6);
-                       cBuilder.setDstIp6(dip6);
-                       cBuilder.setFlowLabel(flowLabel);
-                       cBuilder.setNextHdr(nxtHdr);
-                       cBuilder.setSrcPortStart(sportStart);
-                       cBuilder.setSrcPortEnd(sportEnd);
-                       cBuilder.setDstPortStart(dportStart);
-                       cBuilder.setDstPortEnd(dportEnd);
-                       cBuilder.setTcLow(tcLow);
-                       cBuilder.setTcHigh(tcHigh);
-                       cBuilder.setTcMask(tcMask);
-                       ipv6Classifier = cBuilder.build();
-                       gateBuilder.setIpv6Classifier(ipv6Classifier);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    // TODO FIXME - break apart this method.
+    private boolean validateIpv6Classifier(final Gates gate, final GatesBuilder gateBuilder) {
+        // validate ipv6-classifier
+        String message = "";
+        String error;
+        boolean valid = true;
+        int count = 0;
+        Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+        // Source IPv6 prefix
+        final Ipv6Prefix sip6;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcIp6");
+        if (error == null) {
+            sip6 = ipv6Classifier.getSrcIp6();
+            count++;
+        } else {
+            message += " ipv6-classifier.srcIp invalid: - " + error;
+            sip6 = null;
+            valid = false;
+        }
+        // Destination IPv6 prefix
+        final Ipv6Prefix dip6;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstIp6");
+        if (error == null) {
+            dip6 = ipv6Classifier.getDstIp6();
+            count++;
+        } else {
+            message += " ipv6-classifier.dstIp invalid: - " + error;
+            dip6 = null;
+            valid = false;
+        }
+        // Flow label
+        Long flowLabel;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getFlowLabel");
+        if (error == null) {
+            flowLabel = ipv6Classifier.getFlowLabel();
+            if (flowLabel > 1048575) {
+                message += " ipv6-classifier.flowLabel invalid: - must be 0..1048575";
+                flowLabel = null;
+                valid = false;
+            } else {
+                count++;
+            }
+        } else {
+            message += " ipv6-classifier.flowLabel invalid: - " + error;
+            flowLabel = null;
+            valid = false;
+        }
+        // Next Hdr
+        final TpProtocol nxtHdr;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getNextHdr");
+        if (error == null) {
+            nxtHdr = ipv6Classifier.getNextHdr();
+            count++;
+        } else {
+            message += " ipv6-classifier.nextHdr invalid: - " + error;
+            nxtHdr = null;
+            valid = false;
+        }
+        // Source port range
+        final PortNumber sportStart;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortStart");
+        if (error == null) {
+            sportStart = ipv6Classifier.getSrcPortStart();
+            count++;
+        } else {
+            message += " ipv6-classifier.srcPortStart invalid: - " + error;
+            sportStart = null;
+            valid = false;
+        }
+        final PortNumber sportEnd;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortEnd");
+        if (error == null) {
+            sportEnd = ipv6Classifier.getSrcPortEnd();
+            count++;
+        } else {
+            message += " ipv6-classifier.srcPortEnd invalid: - " + error;
+            sportEnd = null;
+            valid = false;
+        }
+        if (sportStart != null && sportEnd != null) {
+            if (sportStart.getValue() > sportEnd.getValue()) {
+                message += " ipv6-classifier.srcPortStart greater than srcPortEnd";
+                valid = false;
+            }
+        }
+        // Destination port range
+        final PortNumber dportStart;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortStart");
+        if (error == null) {
+            dportStart = ipv6Classifier.getDstPortStart();
+            count++;
+        } else {
+            message += " ipv6-classifier.dstPortStart invalid: - " + error;
+            dportStart = null;
+            valid = false;
+        }
+        final PortNumber dportEnd;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortEnd");
+        if (error == null) {
+            dportEnd = ipv6Classifier.getDstPortEnd();
+            count++;
+        } else {
+            message += " ipv6-classifier.dstPortEnd invalid: - " + error;
+            dportEnd = null;
+            valid = false;
+        }
+        if (dportStart != null && dportEnd != null) {
+            if (dportStart.getValue() > dportEnd.getValue()) {
+                message += " ipv6-classifier.dstPortStart greater than dstPortEnd";
+                valid = false;
+            }
+        }
+        // TC byte
+        final TosByte tcLow;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcLow");
+        if (error == null) {
+            tcLow = ipv6Classifier.getTcLow();
+            count++;
+        } else {
+            message += " ipv6-classifier.tc-low invalid: " + error;
+            tcLow = null;
+            valid = false;
+        }
+        final TosByte tcHigh;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcHigh");
+        if (error == null) {
+            tcHigh = ipv6Classifier.getTcHigh();
+            count++;
+        } else {
+            message += " ipv6-classifier.tc-high invalid: " + error;
+            tcHigh = null;
+            valid = false;
+        }
+        if (tcLow != null && tcHigh != null) {
+            if (tcLow.getValue() > tcHigh.getValue()) {
+                message += " ipv6-classifier.tc-low is greater than tc-high";
+                valid = false;
+            }
+        }
+        final TosByte tcMask;
+        error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcMask");
+        if (error == null) {
+            tcMask = ipv6Classifier.getTcMask();
+        } else {
+            message += " ipv6-classifier.tc-mask invalid: " + error;
+            tcMask = null;
+            valid = false;
+        }
+        if (tcLow != null && tcHigh != null && tcMask == null) {
+            message += " ipv6-classifier.tc-mask missing;";
+            valid = false;
+        }
+        if (count == 0) {
+            message += " ipv6-classifer must have at least one match field";
+            valid = false;
+        }
+        // rebuild ?
+        if (! valid) {
+            final Ipv6ClassifierBuilder cBuilder = new Ipv6ClassifierBuilder();
+            cBuilder.setSrcIp6(sip6);
+            cBuilder.setDstIp6(dip6);
+            cBuilder.setFlowLabel(flowLabel);
+            cBuilder.setNextHdr(nxtHdr);
+            cBuilder.setSrcPortStart(sportStart);
+            cBuilder.setSrcPortEnd(sportEnd);
+            cBuilder.setDstPortStart(dportStart);
+            cBuilder.setDstPortEnd(dportEnd);
+            cBuilder.setTcLow(tcLow);
+            cBuilder.setTcHigh(tcHigh);
+            cBuilder.setTcMask(tcMask);
+            ipv6Classifier = cBuilder.build();
+            gateBuilder.setIpv6Classifier(ipv6Classifier);
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       // TODO FIXME - Do we really want the gate parameter object to be muted by this method?
-       private boolean validateGate(Gates gate, final Response response) {
-               // validate gate elements and null out invalid elements as we go
-               final GatesBuilder gateBuilder = new GatesBuilder();
-               String message = "";
-               boolean rebuild = false;
-               // gate-spec
-               if (! validateGateSpec(gate, gateBuilder, response)) {
-                       rebuild = true;
-               }
-               // traffic-profile
-               if (! validateTrafficProfile(gate, gateBuilder, response)) {
-                       rebuild = true;
-               }
-               // classifiers (one of legacy classifier, ext-classifier, or ipv6 classifier
-               final Classifier classifier = gate.getClassifier();
-               final ExtClassifier extClassifier = gate.getExtClassifier();
-               final Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
-               int count = 0;
-               if (classifier != null) { count++; }
-               if (extClassifier != null) { count++; }
-               if (ipv6Classifier != null) { count++; }
-               if (count < 1){
-                       response.addMessage(" Missing classifer: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
-                       rebuild = true;
-               } else if (count > 1) {
-                       response.addMessage(" Multiple classifiers: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
-                       rebuild = true;
-               } else if (count == 1) {
-                       if (classifier != null) {
-                               // validate classifier
-                               if (! validateClassifier(gate, gateBuilder, response)) {
-                                       rebuild = true;
-                               }
-                       } else if (extClassifier != null) {
-                               //validate ext-classifier
-                               if (! validateExtClassifier(gate, gateBuilder, response)) {
-                                       rebuild = true;
-                               }
-                       } else if (ipv6Classifier != null) {
-                               // TODO FIXME - ipv6Classifier is always null???
-                               // validate ipv6-classifier
-                               if (! validateIpv6Classifier(gate, gateBuilder, response)) {
-                                       rebuild = true;
-                               }
-                       }
-               }
-               // rebuild the gate object with valid data and set the response
-               if (rebuild) {
-                       gateBuilder.setGateId(gate.getGateId());
-                       gateBuilder.setKey(gate.getKey());
-                       // TODO FIXME - the input parameter "gate" is being muted here???
-                       gate = gateBuilder.build();
-                       response.setGateBase(gate);
-                       response.addMessage(message);
-               }
-               return (! rebuild);
-       }
+    // TODO FIXME - Do we really want the gate parameter object to be muted by this method?
+    private boolean validateGate(Gates gate) {
+        // validate gate elements and null out invalid elements as we go
+        final GatesBuilder gateBuilder = new GatesBuilder();
+        String message = "";
+        boolean rebuild = false;
+        // gate-spec
+        if (! validateGateSpec(gate, gateBuilder)) {
+            rebuild = true;
+        }
+        // traffic-profile
+        if (! validateTrafficProfile(gate, gateBuilder)) {
+            rebuild = true;
+        }
+        // classifiers (one of legacy classifier, ext-classifier, or ipv6 classifier
+        final Classifier classifier = gate.getClassifier();
+        final ExtClassifier extClassifier = gate.getExtClassifier();
+        final Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+        int count = 0;
+        if (classifier != null) { count++; }
+        if (extClassifier != null) { count++; }
+        if (ipv6Classifier != null) { count++; }
+        if (count < 1){
+            message = " Missing classifer: must have only 1 of classifier, ext-classifier, or ipv6-classifier";
+            rebuild = true;
+        } else if (count > 1) {
+            message = "Multiple classifiers: must have only 1 of classifier, ext-classifier, or ipv6-classifier";
+            rebuild = true;
+        } else if (count == 1) {
+            if (classifier != null) {
+                // validate classifier
+                if (! validateClassifier(gate, gateBuilder)) {
+                    rebuild = true;
+                }
+            } else if (extClassifier != null) {
+                //validate ext-classifier
+                if (! validateExtClassifier(gate, gateBuilder)) {
+                    rebuild = true;
+                }
+            } else if (ipv6Classifier != null) {
+                // TODO FIXME - ipv6Classifier is always null???
+                // validate ipv6-classifier
+                if (! validateIpv6Classifier(gate, gateBuilder)) {
+                    rebuild = true;
+                }
+            }
+        }
+        // rebuild the gate object with valid data and set the response
+        if (rebuild) {
+            gateBuilder.setGateId(gate.getGateId());
+            gateBuilder.setKey(gate.getKey());
+            // TODO FIXME - the input parameter "gate" is being muted here???
+            gate = gateBuilder.build();
+            logger.error("Gate: {} - {}", gate, message);
+        }
+        return (! rebuild);
+    }
 
-       private boolean validateAmId(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
-               // amId
-               String message = "";
-               String error;
-               boolean valid = true;
-               AmId amId = ccap.getAmId();
-               if (amId == null) {
-                       message += " amId is required;";
-                       valid = false;
-               } else {
-                       final Integer amTag;
-                       error = validateMethod(AmId.class, amId, "getAmTag");
-                       if (error == null) {
-                               amTag = amId.getAmTag();
-                               if (amTag == null) {
-                                       message += " amId.amTag missing;";
-                                       valid = false;
-                               }
-                       } else {
-                               message += " amId.amTag invalid: " + error;
-                               amTag = null;
-                               valid = false;
-                       }
-                       final Integer amType;
-                       error = validateMethod(AmId.class, amId, "getAmType");
-                       if (error == null) {
-                               amType = amId.getAmType();
-                               if (amType == null) {
-                                       message += " amId.amType missing;";
-                                       valid = false;
-                               }
-                       } else {
-                               message += " amId.amType invalid: " + error;
-                               amType = null;
-                               valid = false;
-                       }
-                       if (! valid) {
-                               final AmIdBuilder amIdBuilder = new AmIdBuilder();
-                               amIdBuilder.setAmTag(amTag);
-                               amIdBuilder.setAmType(amType);
-                               amId = amIdBuilder.build();
-                               ccapBuilder.setAmId(amId);
-                       }
-               }
-               if (! valid) {
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateAmId(final Ccaps ccap, final CcapsBuilder ccapBuilder) {
+        // amId
+        String message = "";
+        String error;
+        boolean valid = true;
+        AmId amId = ccap.getAmId();
+        if (amId == null) {
+            message += " amId is required;";
+            valid = false;
+        } else {
+            final Integer amTag;
+            error = validateMethod(AmId.class, amId, "getAmTag");
+            if (error == null) {
+                amTag = amId.getAmTag();
+                if (amTag == null) {
+                    message += " amId.amTag missing;";
+                    valid = false;
+                }
+            } else {
+                message += " amId.amTag invalid: " + error;
+                amTag = null;
+                valid = false;
+            }
+            final Integer amType;
+            error = validateMethod(AmId.class, amId, "getAmType");
+            if (error == null) {
+                amType = amId.getAmType();
+                if (amType == null) {
+                    message += " amId.amType missing;";
+                    valid = false;
+                }
+            } else {
+                message += " amId.amType invalid: " + error;
+                amType = null;
+                valid = false;
+            }
+            if (! valid) {
+                final AmIdBuilder amIdBuilder = new AmIdBuilder();
+                amIdBuilder.setAmTag(amTag);
+                amIdBuilder.setAmType(amType);
+                amId = amIdBuilder.build();
+                ccapBuilder.setAmId(amId);
+            }
+        }
+        if (! valid) {
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       private boolean validateConnection(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
-               // connection
-               String message = "";
-               String error;
-               boolean valid = true;
-               Connection conn = ccap.getConnection();
-               if (conn == null) {
-                       message += " connection is required;";
-                       valid = false;
-               } else {
-                       // IP address
-                       final IpAddress ipAddress;
-                       error = validateMethod(Connection.class, conn, "getIpAddress");
-                       if (error == null) {
-                               ipAddress = conn.getIpAddress();
-                               if (ipAddress == null) {
-                                       message += " connection.ipAddress missing;";
-                                       valid = false;
-                               }
-                       } else {
-                               message += " connection.ipAddress invalid: " + error;
-                               ipAddress = null;
-                               valid = false;
-                       }
-                       // Port number
-                       final PortNumber portNum;
-                       error = validateMethod(Connection.class, conn, "getPort");
-                       if (error == null) {
-                               portNum = conn.getPort();
-                       } else {
-                               message += " connection.port invalid: " + error;
-                               portNum = null;
-                               valid = false;
-                       }
-                       if (! valid) {
-                               final ConnectionBuilder connBuilder = new ConnectionBuilder();
-                               connBuilder.setIpAddress(ipAddress);
-                               connBuilder.setPort(portNum);
-                               conn = connBuilder.build();
-                               ccapBuilder.setConnection(conn);
-                       }
-               }
-               if (! valid) {
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateConnection(final Ccaps ccap, final CcapsBuilder ccapBuilder) {
+        // connection
+        String message = "";
+        String error;
+        boolean valid = true;
+        Connection conn = ccap.getConnection();
+        if (conn == null) {
+            message += " connection is required;";
+            valid = false;
+        } else {
+            // IP address
+            final IpAddress ipAddress;
+            error = validateMethod(Connection.class, conn, "getIpAddress");
+            if (error == null) {
+                ipAddress = conn.getIpAddress();
+                if (ipAddress == null) {
+                    message += " connection.ipAddress missing;";
+                    valid = false;
+                }
+            } else {
+                message += " connection.ipAddress invalid: " + error;
+                ipAddress = null;
+                valid = false;
+            }
+            // Port number
+            final PortNumber portNum;
+            error = validateMethod(Connection.class, conn, "getPort");
+            if (error == null) {
+                portNum = conn.getPort();
+            } else {
+                message += " connection.port invalid: " + error;
+                portNum = null;
+                valid = false;
+            }
+            if (! valid) {
+                final ConnectionBuilder connBuilder = new ConnectionBuilder();
+                connBuilder.setIpAddress(ipAddress);
+                connBuilder.setPort(portNum);
+                conn = connBuilder.build();
+                ccapBuilder.setConnection(conn);
+            }
+        }
+        if (! valid) {
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       private boolean validateSubscriberSubnets(final Ccaps ccap, final CcapsBuilder ccapBuilder,
-                                                                                         final Response response) {
-               // subscriber-subnets
-               String message = "";
-               String error;
-               boolean valid = true;
-               List<IpPrefix> subnets = null;
-               error = validateMethod(Ccaps.class, ccap, "getSubscriberSubnets");
-               if (error == null) {
-                       subnets = ccap.getSubscriberSubnets();
-                       if (subnets == null) {
-                               message += " subscriber-subnets is required;";
-                               valid = false;
-                       }
-               } else {
-                       message += " subscriber-subnets contains invalid IpPrefix - must be <ipaddress>/<prefixlen> format;" + error;
-                       valid = false;
-               }
-               if (! valid) {
-                       // TODO FIXME - subnets is always null???
-                       ccapBuilder.setSubscriberSubnets(subnets);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateSubscriberSubnets(final Ccaps ccap, final CcapsBuilder ccapBuilder) {
+        // subscriber-subnets
+        String message = "";
+        String error;
+        boolean valid = true;
+        List<IpPrefix> subnets = null;
+        error = validateMethod(Ccaps.class, ccap, "getSubscriberSubnets");
+        if (error == null) {
+            subnets = ccap.getSubscriberSubnets();
+            if (subnets == null) {
+                message += " subscriber-subnets is required;";
+                valid = false;
+            }
+        } else {
+            message += " subscriber-subnets contains invalid IpPrefix - must be <ipaddress>/<prefixlen> format;" + error;
+            valid = false;
+        }
+        if (! valid) {
+            // TODO FIXME - subnets is always null???
+            ccapBuilder.setSubscriberSubnets(subnets);
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       private boolean validateUpstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
-               // upstream-scns
-               String message = "";
-               String error;
-               boolean valid = true;
-               List<ServiceClassName> usScns = null;
-               error = validateMethod(Ccaps.class, ccap, "getUpstreamScns");
-               if (error == null) {
-                       usScns = ccap.getUpstreamScns();
-                       if (usScns == null) {
-                               message += " upstream-scns is required;";
-                               valid = false;
-                       }
-               } else {
-                       message += " upstream-scns contains invalid SCN - must be 2-16 characters;" + error;
-                       valid = false;
-               }
-               if (! valid) {
-                       // TODO FIXME - usScns is always null???
-                       ccapBuilder.setUpstreamScns(usScns);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateUpstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder) {
+        // upstream-scns
+        String message = "";
+        String error;
+        boolean valid = true;
+        List<ServiceClassName> usScns = null;
+        error = validateMethod(Ccaps.class, ccap, "getUpstreamScns");
+        if (error == null) {
+            usScns = ccap.getUpstreamScns();
+            if (usScns == null) {
+                message += " upstream-scns is required;";
+                valid = false;
+            }
+        } else {
+            message += " upstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+            valid = false;
+        }
+        if (! valid) {
+            // TODO FIXME - usScns is always null???
+            ccapBuilder.setUpstreamScns(usScns);
+            logger.error(message);
+        }
+        return valid;
+    }
 
-       private boolean validateDownstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
-               // downstream-scns
-               String message = "";
-               boolean valid = true;
-               List<ServiceClassName> dsScns = null;
-               final String error = validateMethod(Ccaps.class, ccap, "getDownstreamScns");
-               if (error == null) {
-                       dsScns = ccap.getDownstreamScns();
-                       if (dsScns == null) {
-                               message += " downstream-scns is required;";
-                               valid = false;
-                       }
-               } else {
-                       message += " downstream-scns contains invalid SCN - must be 2-16 characters;" + error;
-                       valid = false;
-               }
-               if (! valid) {
-                       // TODO FIXME - dsScns is always null???
-                       ccapBuilder.setDownstreamScns(dsScns);
-                       response.addMessage(message);
-               }
-               return valid;
-       }
+    private boolean validateDownstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder) {
+        // downstream-scns
+        String message = "";
+        boolean valid = true;
+        List<ServiceClassName> dsScns = null;
+        final String error = validateMethod(Ccaps.class, ccap, "getDownstreamScns");
+        if (error == null) {
+            dsScns = ccap.getDownstreamScns();
+            if (dsScns == null) {
+                message += " downstream-scns is required;";
+                valid = false;
+            }
+        } else {
+            message += " downstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+            valid = false;
+        }
+        if (! valid) {
+            // TODO FIXME - dsScns is always null???
+            ccapBuilder.setDownstreamScns(dsScns);
+            logger.error(message);
+        }
+        return valid;
+    }
 
 
-       // TODO FIXME - Do we really want the ccap parameter object to be muted by this method?
-       private boolean validateCcap(Ccaps ccap, final Response response) {
-               // validate ccap and null out invalid elements as we go
-               final CcapsBuilder ccapBuilder = new CcapsBuilder();
-               String message = "";
-               boolean rebuild = false;
-               // amId
-               if ( ! validateAmId(ccap, ccapBuilder, response))        {
-                       rebuild = true;
-               }
-               // connection
-               if ( ! validateConnection(ccap, ccapBuilder, response))        {
-                       rebuild = true;
-               }
-               // subscriber-subnets
-               if ( ! validateSubscriberSubnets(ccap, ccapBuilder, response))        {
-                       rebuild = true;
-               }
-               // upstream-scns
-               if ( ! validateUpstreamScns(ccap, ccapBuilder, response))        {
-                       rebuild = true;
-               }
-               // downstream-scns
-               if ( ! validateDownstreamScns(ccap, ccapBuilder, response))        {
-                       rebuild = true;
-               }
-               // rebuild the ccap object with valid data and set the response
-               if (rebuild) {
-                       ccapBuilder.setCcapId(ccap.getCcapId());
-                       ccapBuilder.setKey(ccap.getKey());
-                       // TODO FIXME - the input parameter "ccap" is being muted here???
-                       ccap = ccapBuilder.build();
-                       response.setCcapBase(ccap);
-                       response.addMessage(message);
-               }
-               return (! rebuild);
-       }
+    // TODO FIXME - Do we really want the ccap parameter object to be muted by this method?
+    private boolean validateCcap(Ccaps ccap) {
+        // validate ccap and null out invalid elements as we go
+        final CcapsBuilder ccapBuilder = new CcapsBuilder();
+        String message = "";
+        boolean rebuild = false;
+        // amId
+        if ( ! validateAmId(ccap, ccapBuilder))        {
+            rebuild = true;
+        }
+        // connection
+        if ( ! validateConnection(ccap, ccapBuilder))        {
+            rebuild = true;
+        }
+        // subscriber-subnets
+        if ( ! validateSubscriberSubnets(ccap, ccapBuilder))        {
+            rebuild = true;
+        }
+        // upstream-scns
+        if ( ! validateUpstreamScns(ccap, ccapBuilder))        {
+            rebuild = true;
+        }
+        // downstream-scns
+        if ( ! validateDownstreamScns(ccap, ccapBuilder))        {
+            rebuild = true;
+        }
+        // rebuild the ccap object with valid data and set the response
+        if (rebuild) {
+            ccapBuilder.setCcapId(ccap.getCcapId());
+            ccapBuilder.setKey(ccap.getKey());
+            // TODO FIXME - the input parameter "ccap" is being muted here???
+            ccap = ccapBuilder.build();
+            logger.error("Ccap: {} - {} ", ccap, message);
+        }
+        return (! rebuild);
+    }
 }