ONOS-6189
[ONOS-YANG-DEMO1]Inner node cannot have empty children map error is occurring

Change-Id: Ic2f2734e3cda836ac6b5e2548e14532bee58cfaf
diff --git a/apps/netconf/client/BUCK b/apps/netconf/client/BUCK
index 804a67f..2f2960b 100644
--- a/apps/netconf/client/BUCK
+++ b/apps/netconf/client/BUCK
@@ -9,6 +9,7 @@
   '//lib:onos-yang-model',
   '//lib:onos-yang-runtime',
   '//apps/config:onos-apps-config',
+  '//utils/misc:onlab-misc',
   '//protocols/netconf/api:onos-protocols-netconf-api',
   '//utils/osgi:onlab-osgi',
 ]
diff --git a/apps/netconf/client/src/main/java/org/onosproject/netconf/client/impl/NetconfActiveComponent.java b/apps/netconf/client/src/main/java/org/onosproject/netconf/client/impl/NetconfActiveComponent.java
index 16c226d..ae6b453 100644
--- a/apps/netconf/client/src/main/java/org/onosproject/netconf/client/impl/NetconfActiveComponent.java
+++ b/apps/netconf/client/src/main/java/org/onosproject/netconf/client/impl/NetconfActiveComponent.java
@@ -40,6 +40,8 @@
 import org.onosproject.yang.model.NodeKey;
 import org.onosproject.yang.model.ResourceId;
 import org.onosproject.yang.runtime.DefaultResourceData;
+import org.onlab.util.AbstractAccumulator;
+import org.onlab.util.Accumulator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,6 +51,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Timer;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
@@ -60,7 +63,6 @@
     private static final Logger log = LoggerFactory.getLogger(NetconfActiveComponent.class);
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DynamicConfigService cfgService;
-    public static final String DEVNMSPACE = "ne-l3vpn-api";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetconfTranslator netconfTranslator;
@@ -71,9 +73,16 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetconfController controller;
 
-    public static final String DEVICES = "devices";
-    public static final String DEVICE = "device";
-    public static final String DEVICE_ID = "deviceid";
+    private final Accumulator<DynamicConfigEvent> accumulator = new InternalEventAccummulator();
+    private static final String DEVNMSPACE = "ne-l3vpn-api";
+    private static final String DEVICES = "devices";
+    private static final String DEVICE = "device";
+    private static final String DEVICE_ID = "deviceid";
+
+    //Symbolic constants for use with the accumulator
+    private static final int MAX_EVENTS = 1000;
+    private static final int MAX_BATCH_MS = 5000;
+    private static final int MAX_IDLE_MS = 1000;
 
     private ResourceId resId = new ResourceId.Builder()
             .addBranchPointSchema(DEVICES, DEVNMSPACE)
@@ -129,30 +138,10 @@
         return mastershipService.isLocalMaster(deviceId);
     }
 
+
     @Override
     public void event(DynamicConfigEvent event) {
-        Filter filt = new Filter();
-        DataNode node = cfgService.readNode(event.subject(), filt);
-        DeviceId deviceId = getDeviceId(node);
-        if (!isMaster(deviceId)) {
-            log.info("NetConfListener: not master, ignoring config for {}", event.type());
-            return;
-        }
-        initiateConnection(deviceId);
-        switch (event.type()) {
-            case NODE_ADDED:
-            case NODE_UPDATED:
-            case NODE_REPLACED:
-                configUpdate(node, deviceId, event.subject());
-                break;
-            case NODE_DELETED:
-                configDelete(node, deviceId, event.subject());
-                break;
-            case UNKNOWN_OPRN:
-            default:
-                log.warn("NetConfListener: unknown event: {}", event.type());
-                break;
-        }
+        accumulator.add(event);
     }
 
     /**
@@ -262,7 +251,46 @@
                 //}
             } catch (Exception ex) {
                 throw new RuntimeException(new NetconfException("Unable to connect to NETCONF device on " +
-                                                                        deviceId, ex));
+                        deviceId, ex));
+            }
+        }
+    }
+
+    /* Accumulates events to allow processing after a desired number of events were accumulated.
+    */
+    private class InternalEventAccummulator extends AbstractAccumulator<DynamicConfigEvent> {
+        protected InternalEventAccummulator() {
+            super(new Timer("dyncfgevt-timer"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
+        }
+        @Override
+        public void processItems(List<DynamicConfigEvent> events) {
+            DynamicConfigEvent event = null;
+            for (DynamicConfigEvent e : events) {
+                //checkIfRelevant already filters only the relevant events
+                event = e;
+                checkNotNull(event, "process:Event cannot be null");
+                Filter filt = new Filter();
+                DataNode node = cfgService.readNode(event.subject(), filt);
+                DeviceId deviceId = getDeviceId(node);
+                if (!isMaster(deviceId)) {
+                    log.info("NetConfListener: not master, ignoring config for {}", event.type());
+                    return;
+                }
+                initiateConnection(deviceId);
+                switch (event.type()) {
+                    case NODE_ADDED:
+                    case NODE_UPDATED:
+                    case NODE_REPLACED:
+                        configUpdate(node, deviceId, event.subject());
+                        break;
+                    case NODE_DELETED:
+                        configDelete(node, deviceId, event.subject());
+                        break;
+                    case UNKNOWN_OPRN:
+                    default:
+                        log.warn("NetConfListener: unknown event: {}", event.type());
+                        break;
+                }
             }
         }
     }