Merge changes Ieef23a07,I8057763e
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / sal / dom / broker / impl / SchemaAwareDataStoreAdapter.java
index b32d906d1e70cc8dc5997fea3c57c3379943b6b5..1a572d157dba9f8272140495b8eabf9669df11bc 100644 (file)
@@ -11,6 +11,9 @@ import static com.google.common.base.Preconditions.checkState;
 
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.Future;
 
@@ -27,10 +30,13 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,9 +45,9 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
 
 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
-        DataStore, //
-        SchemaServiceListener, //
-        AutoCloseable {
+DataStore, //
+SchemaContextListener, //
+AutoCloseable {
 
     private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
 
@@ -50,7 +56,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     private final DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
 
     @Override
-    public boolean containsConfigurationPath(InstanceIdentifier path) {
+    public boolean containsConfigurationPath(final InstanceIdentifier path) {
         try {
             getDelegateReadLock().lock();
             return getDelegate().containsConfigurationPath(path);
@@ -61,7 +67,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    public boolean containsOperationalPath(InstanceIdentifier path) {
+    public boolean containsOperationalPath(final InstanceIdentifier path) {
         try {
             getDelegateReadLock().lock();
             return getDelegate().containsOperationalPath(path);
@@ -94,18 +100,18 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+    public CompositeNode readConfigurationData(final InstanceIdentifier path) {
         return reader.readConfigurationData(path);
     }
 
     @Override
-    public CompositeNode readOperationalData(InstanceIdentifier path) {
+    public CompositeNode readOperationalData(final InstanceIdentifier path) {
         return reader.readOperationalData(path);
     }
 
     @Override
     public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
-            DataModification<InstanceIdentifier, CompositeNode> modification) {
+            final DataModification<InstanceIdentifier, CompositeNode> modification) {
         validateAgainstSchema(modification);
         NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
         cleanedUp.status = TransactionStatus.SUBMITED;
@@ -116,11 +122,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         return validationEnabled;
     }
 
-    public void setValidationEnabled(boolean validationEnabled) {
+    public void setValidationEnabled(final boolean validationEnabled) {
         this.validationEnabled = validationEnabled;
     }
 
-    private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
+    private void validateAgainstSchema(final DataModification<InstanceIdentifier, CompositeNode> modification) {
         if (!validationEnabled) {
             return;
         }
@@ -132,12 +138,12 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
+    protected void onDelegateChanged(final DataStore oldDelegate, final DataStore newDelegate) {
         // NOOP
     }
 
     @Override
-    public void onGlobalContextUpdated(SchemaContext context) {
+    public void onGlobalContextUpdated(final SchemaContext context) {
         this.schema = context;
     }
 
@@ -146,9 +152,9 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         this.schema = null;
     }
 
-    protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
-            boolean config) {
-        long startTime = System.nanoTime();
+    protected CompositeNode mergeData(final InstanceIdentifier path, final CompositeNode stored, final CompositeNode modified,
+            final boolean config) {
+        // long startTime = System.nanoTime();
         try {
             DataSchemaNode node = schemaNodeFor(path);
             return YangDataOperations.merge(node, stored, modified, config);
@@ -158,30 +164,37 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         }
     }
 
-    private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
+    private DataSchemaNode schemaNodeFor(final InstanceIdentifier path) {
         checkState(schema != null, "YANG Schema is not available");
         return YangSchemaUtils.getSchemaNode(schema, path);
     }
 
     private NormalizedDataModification prepareMergedTransaction(
-            DataModification<InstanceIdentifier, CompositeNode> original) {
+            final DataModification<InstanceIdentifier, CompositeNode> original) {
         NormalizedDataModification normalized = new NormalizedDataModification(original);
-        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
-            normalized.putConfigurationData(entry.getKey(), entry.getValue());
-        }
-        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
-            normalized.putOperationalData(entry.getKey(), entry.getValue());
-        }
+        LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(),
+                original.getRemovedConfigurationData(), original.getRemovedConfigurationData());
+        LOG.trace("Transaction: {} Created Configuration {}, Created Operational {}", original.getIdentifier(),
+                original.getCreatedConfigurationData().entrySet(), original.getCreatedOperationalData().entrySet());
+        LOG.trace("Transaction: {} Updated Configuration {}, Updated Operational {}", original.getIdentifier(),
+                original.getUpdatedConfigurationData().entrySet(), original.getUpdatedOperationalData().entrySet());
+
         for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
             normalized.deepRemoveConfigurationData(entry);
         }
         for (InstanceIdentifier entry : original.getRemovedOperationalData()) {
             normalized.deepRemoveOperationalData(entry);
         }
+        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
+            normalized.putDeepConfigurationData(entry.getKey(), entry.getValue());
+        }
+        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
+            normalized.putDeepOperationalData(entry.getKey(), entry.getValue());
+        }
         return normalized;
     }
 
-    private Iterable<InstanceIdentifier> getConfigurationSubpaths(InstanceIdentifier entry) {
+    private Iterable<InstanceIdentifier> getConfigurationSubpaths(final InstanceIdentifier entry) {
         // FIXME: This should be replaced by index
         Iterable<InstanceIdentifier> paths = getStoredConfigurationPaths();
 
@@ -189,15 +202,15 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     }
 
-    public Iterable<InstanceIdentifier> getOperationalSubpaths(InstanceIdentifier entry) {
+    public Iterable<InstanceIdentifier> getOperationalSubpaths(final InstanceIdentifier entry) {
         // FIXME: This should be indexed
         Iterable<InstanceIdentifier> paths = getStoredOperationalPaths();
 
         return getChildrenPaths(entry, paths);
     }
 
-    private static final Iterable<InstanceIdentifier> getChildrenPaths(InstanceIdentifier entry,
-            Iterable<InstanceIdentifier> paths) {
+    private static final Iterable<InstanceIdentifier> getChildrenPaths(final InstanceIdentifier entry,
+            final Iterable<InstanceIdentifier> paths) {
         ImmutableSet.Builder<InstanceIdentifier> children = ImmutableSet.builder();
         for (InstanceIdentifier potential : paths) {
             if (entry.contains(potential)) {
@@ -209,7 +222,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
         @Override
-        public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
+        public int compare(final Entry<InstanceIdentifier, CompositeNode> o1, final Entry<InstanceIdentifier, CompositeNode> o2) {
             InstanceIdentifier o1Key = o1.getKey();
             InstanceIdentifier o2Key = o2.getKey();
             return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
@@ -229,7 +242,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 CompositeNode original = getDelegate().readConfigurationData(path);
                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
                 if (original != null) {
-                    childNodes.addAll(original.getChildren());
+                    childNodes.addAll(original.getValue());
                     qname = original.getNodeType();
                 } else {
                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
@@ -238,7 +251,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
                         .filter(new Predicate<InstanceIdentifier>() {
                             @Override
-                            public boolean apply(InstanceIdentifier input) {
+                            public boolean apply(final InstanceIdentifier input) {
                                 if (path.contains(input)) {
                                     int nesting = input.getPath().size() - path.getPath().size();
                                     if (nesting == 1) {
@@ -272,7 +285,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 CompositeNode original = getDelegate().readOperationalData(path);
                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
                 if (original != null) {
-                    childNodes.addAll(original.getChildren());
+                    childNodes.addAll(original.getValue());
                     qname = original.getNodeType();
                 } else {
                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
@@ -281,7 +294,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
                         .filter(new Predicate<InstanceIdentifier>() {
                             @Override
-                            public boolean apply(InstanceIdentifier input) {
+                            public boolean apply(final InstanceIdentifier input) {
                                 if (path.contains(input)) {
                                     int nesting = input.getPath().size() - path.getPath().size();
                                     if (nesting == 1) {
@@ -308,10 +321,12 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
 
+        private final String CONFIGURATIONAL_DATA_STORE_MARKER = "configurational";
+        private final String OPERATIONAL_DATA_STORE_MARKER = "operational";
         private final Object identifier;
         private TransactionStatus status;
 
-        public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
+        public NormalizedDataModification(final DataModification<InstanceIdentifier, CompositeNode> original) {
             super(getDelegate());
             identifier = original;
             status = TransactionStatus.NEW;
@@ -324,7 +339,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
          *
          * @param entry
          */
-        public void deepRemoveOperationalData(InstanceIdentifier entry) {
+        public void deepRemoveOperationalData(final InstanceIdentifier entry) {
             Iterable<InstanceIdentifier> paths = getOperationalSubpaths(entry);
             removeOperationalData(entry);
             for (InstanceIdentifier potential : paths) {
@@ -332,7 +347,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
-        public void deepRemoveConfigurationData(InstanceIdentifier entry) {
+        public void deepRemoveConfigurationData(final InstanceIdentifier entry) {
             Iterable<InstanceIdentifier> paths = getConfigurationSubpaths(entry);
             removeConfigurationData(entry);
             for (InstanceIdentifier potential : paths) {
@@ -340,6 +355,14 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
+        public void putDeepConfigurationData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
+            this.putCompositeNodeData(entryKey, entryData, CONFIGURATIONAL_DATA_STORE_MARKER);
+        }
+
+        public void putDeepOperationalData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
+            this.putCompositeNodeData(entryKey, entryData, OPERATIONAL_DATA_STORE_MARKER);
+        }
+
         @Override
         public Object getIdentifier() {
             return this.identifier;
@@ -356,16 +379,82 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         }
 
         @Override
-        protected CompositeNode mergeConfigurationData(InstanceIdentifier path, CompositeNode stored,
-                CompositeNode modified) {
+        protected CompositeNode mergeConfigurationData(final InstanceIdentifier path, final CompositeNode stored,
+                final CompositeNode modified) {
             return mergeData(path, stored, modified, true);
         }
 
         @Override
-        protected CompositeNode mergeOperationalData(InstanceIdentifier path, CompositeNode stored,
-                CompositeNode modified) {
+        protected CompositeNode mergeOperationalData(final InstanceIdentifier path, final CompositeNode stored,
+                final CompositeNode modified) {
             return mergeData(path, stored, modified, false);
         }
-    }
 
+        private void putData(final InstanceIdentifier entryKey, final CompositeNode entryData, final String dataStoreIdentifier) {
+            if (dataStoreIdentifier != null && entryKey != null && entryData != null) {
+                switch (dataStoreIdentifier) {
+                case (CONFIGURATIONAL_DATA_STORE_MARKER):
+                    this.putConfigurationData(entryKey, entryData);
+                break;
+                case (OPERATIONAL_DATA_STORE_MARKER):
+                    this.putOperationalData(entryKey, entryData);
+                break;
+
+                default:
+                    LOG.error(dataStoreIdentifier + " is NOT valid DataStore switch marker");
+                    throw new RuntimeException(dataStoreIdentifier + " is NOT valid DataStore switch marker");
+                }
+            }
+        }
+
+        private void putCompositeNodeData(final InstanceIdentifier entryKey, final CompositeNode entryData,
+                final String dataStoreIdentifier) {
+            this.putData(entryKey, entryData, dataStoreIdentifier);
+
+            for (Node<?> child : entryData.getValue()) {
+                InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType())
+                        .toInstance();
+                if (child instanceof CompositeNode) {
+                    DataSchemaNode subSchema = schemaNodeFor(subEntryId);
+                    CompositeNode compNode = (CompositeNode) child;
+                    InstanceIdentifier instanceId = null;
+
+                    if (subSchema instanceof ListSchemaNode) {
+                        ListSchemaNode listSubSchema = (ListSchemaNode) subSchema;
+                        Map<QName, Object> mapOfSubValues = this.getValuesFromListSchema(listSubSchema,
+                                (CompositeNode) child);
+                        if (mapOfSubValues != null) {
+                            instanceId = InstanceIdentifier.builder(entryKey)
+                                    .nodeWithKey(listSubSchema.getQName(), mapOfSubValues).toInstance();
+                        }
+                    } else if (subSchema instanceof ContainerSchemaNode) {
+                        ContainerSchemaNode containerSchema = (ContainerSchemaNode) subSchema;
+                        instanceId = InstanceIdentifier.builder(entryKey).node(subSchema.getQName()).toInstance();
+                    }
+                    if (instanceId != null) {
+                        this.putCompositeNodeData(instanceId, compNode, dataStoreIdentifier);
+                    }
+                }
+            }
+        }
+
+        private Map<QName, Object> getValuesFromListSchema(final ListSchemaNode listSchema, final CompositeNode entryData) {
+            List<QName> keyDef = listSchema.getKeyDefinition();
+            if (keyDef != null && !keyDef.isEmpty()) {
+                Map<QName, Object> map = new HashMap<QName, Object>();
+                for (QName key : keyDef) {
+                    List<Node<?>> data = entryData.get(key);
+                    if (data != null && !data.isEmpty()) {
+                        for (Node<?> nodeData : data) {
+                            if (nodeData instanceof SimpleNode<?>) {
+                                map.put(key, data.get(0).getValue());
+                            }
+                        }
+                    }
+                }
+                return map;
+            }
+            return null;
+        }
+    }
 }