Fixed bug in Data store where multiple readers could overwrite 74/3274/2
authorTony Tkacik <ttkacik@cisco.com>
Sun, 1 Dec 2013 01:39:43 +0000 (02:39 +0100)
committerTony Tkacik <ttkacik@cisco.com>
Sun, 1 Dec 2013 09:21:28 +0000 (10:21 +0100)
other augmentations

  - Added configuration / operational data validation - Commit
    with operational data stored in configuration store will fail.
  - Added initial data change event.

Change-Id: I5383cc28286bff98b95b11b63c56cd175ea2c7e9
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
28 files changed:
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java [new file with mode: 0644]

index a5e5c74..51b0084 100644 (file)
@@ -51,7 +51,7 @@
                     </dependency>
                 </dependencies>
             </plugin>
-            
+
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>${osgi.core.version}</version>
-        <scope>provided</scope>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
-       <dependency>
-       <groupId>org.eclipse.xtend</groupId>
-       <artifactId>org.eclipse.xtend.standalone</artifactId>
-       <version>2.4.3</version>
-       <scope>runtime</scope>
-       </dependency> 
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.standalone</artifactId>
+            <version>2.4.3</version>
+            <scope>runtime</scope>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
             <version>${slf4j.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-statistics</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.reflections</groupId>
             <artifactId>reflections</artifactId>
index 35f4874..d05967c 100644 (file)
@@ -7,7 +7,6 @@ import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdenti
 import org.opendaylight.yangtools.yang.binding.BindingCodec;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
 
 public class CodecMapping {
 
@@ -16,7 +15,7 @@ public class CodecMapping {
     public static final String COMPOSITE_TO_CASE = "COMPOSITE_TO_CASE";
     public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC";
     
-    public static void setIdentifierCodec(Class obj,InstanceIdentifierCodec codec) {
+    public static void setIdentifierCodec(Class<?> obj,InstanceIdentifierCodec codec) {
         Field instanceIdField;
         try {
             instanceIdField = obj.getField(INSTANCE_IDENTIFIER_CODEC);
index 048dc3a..d86d2f4 100644 (file)
@@ -3,7 +3,6 @@ package org.opendaylight.controller.sal.binding.dom.serializer.impl;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 
 public class CodecTypeUtils {
 
@@ -13,5 +12,4 @@ public class CodecTypeUtils {
         Identifier<? extends Identifiable<?>> identifier = (Identifier<? extends Identifiable<?>>) key;
         return new IdentifiableItem(identifiableType,identifier);
     }
-
 }
index b811008..a55d4b9 100644 (file)
@@ -2,7 +2,6 @@ package org.opendaylight.controller.sal.binding.dom.serializer.impl;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
-import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -337,15 +336,11 @@ public class LazyGeneratedCodecRegistry implements //
 
     @Override
     public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
-        // TODO Auto-generated method stub
-
     }
 
     @Override
     public void onCaseCodecCreated(Class<?> choiceClass,
             Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
-        // TODO Auto-generated method stub
-
     }
 
     @Override
index 01390d7..ab2e96f 100644 (file)
@@ -45,6 +45,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentation
 import java.util.Iterator
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
 import java.util.concurrent.ConcurrentHashMap
+import static extension org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils.*;
 
 class TransformerGenerator {
 
@@ -214,7 +215,7 @@ class TransformerGenerator {
         if (transformer !== null) {
             return transformer;
         }
-        return withClassLoaderAndLock(cls.classLoader,lock) [|
+        return withClassLoaderAndLock(cls.classLoader, lock) [ |
             val valueTransformer = generateValueTransformer(cls, type);
             return valueTransformer;
         ]
@@ -222,6 +223,7 @@ class TransformerGenerator {
 
     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = typeSpec.allProperties;
             val ctCls = createClass(inputType.codecClassName) [
@@ -260,13 +262,15 @@ class TransformerGenerator {
                             }
                             «QName.name» _localQName = $1;
                             java.util.Map _compositeNode = (java.util.Map) $2;
+                            boolean _is_empty = true;
                             «FOR key : node.keyDefinition»
                                 «val propertyName = key.getterName»
                                 «val keyDef = node.getDataChildByName(key)»
                                 «val property = properties.get(propertyName)»
                                 «deserializeProperty(keyDef, property, propertyName)»;
                             «ENDFOR»
-                            «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
+                            «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
+                            keyConstructorList»);
                             return _value;
                         }
                     '''
@@ -299,11 +303,12 @@ class TransformerGenerator {
     private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
         ChoiceCaseNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 implementsType(BINDING_CODEC)
-                staticQNameField(inputType);
+                staticQNameField(node.QName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
                 method(Object, "toDomStatic", QName, Object) [
@@ -313,7 +318,7 @@ class TransformerGenerator {
                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
                             java.util.List _childNodes = new java.util.ArrayList();
                             «type.resolvedName» value = («type.resolvedName») $2;
-                            «transformDataContainerBody(type,type.allProperties, node)»
+                            «transformDataContainerBody(type, type.allProperties, node)»
                             return ($r) _childNodes;
                         }
                     '''
@@ -356,10 +361,11 @@ class TransformerGenerator {
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
         Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(inputType);
+                staticQNameField(node.QName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
                 implementsType(BINDING_CODEC)
@@ -403,11 +409,12 @@ class TransformerGenerator {
     private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
         Class<?> inputType, GeneratedType type, AugmentationSchema node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = type.allProperties
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(inputType);
+                staticQNameField(node.augmentationQName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
                 implementsType(BINDING_CODEC)
@@ -453,12 +460,15 @@ class TransformerGenerator {
                             java.util.Map _compositeNode = (java.util.Map) $2;
                             //System.out.println(_localQName + " " + _compositeNode);
                             «type.builderName» _builder = new «type.builderName»();
+                            boolean _is_empty = true;
                             «FOR child : node.childNodes»
                                 «val signature = properties.getFor(child)»
                                 «deserializeProperty(child, signature.value, signature.key)»
-                                
                                 _builder.«signature.key.toSetter»(«signature.key»);
                             «ENDFOR»
+                            if(_is_empty) {
+                                return null;
+                            }
                             return _builder.build();
                         }
                     '''
@@ -482,6 +492,7 @@ class TransformerGenerator {
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
         Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
@@ -639,11 +650,13 @@ class TransformerGenerator {
     private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
         DataNodeContainer node) {
         val ret = '''
-            «FOR child : node.childNodes.filter[!augmenting]»
+            boolean _is_empty = true;
+            «FOR child : node.childNodes»
                 «val signature = properties.getFor(child)»
-                «deserializeProperty(child, signature.value, signature.key)»
-                
-                _builder.«signature.key.toSetter»(«signature.key»);
+                «IF signature !== null»
+                    «deserializeProperty(child, signature.value, signature.key)»
+                    _builder.«signature.key.toSetter»(«signature.key»);
+                «ENDIF»
             «ENDFOR»
         '''
         return ret;
@@ -658,7 +671,9 @@ class TransformerGenerator {
                 //System.out.println("Aug. key:" + _entry.getKey());
                 Class _type = (Class) _entry.getKey();
                 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
-                _builder.addAugmentation(_type,_value);
+                if(_value != null) {
+                    _builder.addAugmentation(_type,_value);
+                }
             }
         }
     '''
@@ -675,6 +690,7 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
+                _is_empty = false;
                 //System.out.println("  item" + _listItem);
                 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
                 //System.out.println("  value" + _value);
@@ -696,6 +712,7 @@ class TransformerGenerator {
             java.util.Iterator _iterator = _dom_«propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
+                _is_empty = false;
                 Object _listItem = _iterator.next();
                 if(_listItem instanceof java.util.Map.Entry) {
                     Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
@@ -712,6 +729,7 @@ class TransformerGenerator {
             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
         «type.resolvedName» «propertyName» = null;
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+            _is_empty = false;
             java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
             Object _inner_value = _dom_«propertyName».getValue();
             «propertyName» = «deserializeValue(type, "_inner_value")»;
@@ -724,7 +742,7 @@ class TransformerGenerator {
             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
         «type.resolvedName» «propertyName» = null;
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
-            
+            _is_empty = false;
             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
             «propertyName» =  «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
         }
@@ -732,10 +750,13 @@ class TransformerGenerator {
 
     private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
         «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+        if(«propertyName» != null) {
+            _is_empty = false;
+        }
     '''
 
     private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
-        («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
+        («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
     '''
 
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
@@ -758,7 +779,7 @@ class TransformerGenerator {
             val hasYangBinding = hasBinding
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                if(hasYangBinding) {
+                if (hasYangBinding) {
                     implementsType(BINDING_CODEC)
                     staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                     implementsType(BindingDeserializer.asCtClass)
@@ -865,14 +886,13 @@ class TransformerGenerator {
         return null;
     }
 
-    private def dispatch Class<?> generateValueTransformer(
-        Class<?> inputType, Enumeration typeSpec) {
+    private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 //implementsType(BINDING_CODEC)
-                
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
@@ -981,12 +1001,6 @@ class TransformerGenerator {
     */
     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
 
-    private def staticQNameField(CtClass it, Class<?> node) {
-        val field = new CtField(ctQName, "QNAME", it);
-        field.modifiers = PUBLIC + FINAL + STATIC;
-        addField(field, '''«node.name».QNAME''')
-    }
-
     private def staticQNameField(CtClass it, QName node) {
         val field = new CtField(ctQName, "QNAME", it);
         field.modifiers = PUBLIC + FINAL + STATIC;
@@ -999,7 +1013,7 @@ class TransformerGenerator {
             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1010,7 +1024,7 @@ class TransformerGenerator {
             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1021,7 +1035,7 @@ class TransformerGenerator {
         «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1036,18 +1050,20 @@ class TransformerGenerator {
         }
     '''
 
-    private def transformDataContainerBody(Type type,Map<String, Type> properties, DataNodeContainer node) {
+    private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
         val ret = '''
-            «FOR child : node.childNodes.filter[!augmenting]»
-                «var signature = properties.getFor(child)»
-                //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
-                «serializeProperty(child, signature.value, signature.key)»
+            «FOR child : node.childNodes»
+                «val signature = properties.getFor(child)»
+                «IF signature !== null»
+                    //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
+                    «serializeProperty(child, signature.value, signature.key)»
+                «ENDIF»
             «ENDFOR»
         '''
         return ret;
     }
 
-    def serializeAugmentations() '''
+    private def serializeAugmentations() '''
         java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
         if(_augmentations != null) {
             _childNodes.addAll(_augmentations);
@@ -1055,12 +1071,15 @@ class TransformerGenerator {
     '''
 
     def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
-        val sig = map.get(node.getterName);
-        if (sig == null) {
-
+        var sig = map.get(node.getterName);
+        if (sig != null) {
+            return new SimpleEntry(node.getterName, sig);
+        }
+        sig = map.get(node.booleanGetterName);
+        if (sig != null) {
             return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
         }
-        return new SimpleEntry(node.getterName, sig);
+        return null;
     }
 
     private static def String getBooleanGetterName(DataSchemaNode node) {
@@ -1078,6 +1097,7 @@ class TransformerGenerator {
     private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
         String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
+        //System.out.println("«propertyName»:" + «propertyName»);
         if(«propertyName» != null) {
             java.util.Iterator _iterator = «propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
index ea48374..254b872 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 
 public class CommitHandlersTransactions {
 
-    private static class AllwaysSuccessfulTransaction<P,D> implements DataCommitTransaction<P, D> {
+    private static class AllwaysSuccessfulTransaction<P extends Path<P>,D> implements DataCommitTransaction<P, D> {
         
         private final  DataModification<P, D> modification;
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java
new file mode 100644 (file)
index 0000000..b7a21cb
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.sal.binding.impl.util;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+import com.google.common.base.Preconditions;
+
+public class YangSchemaUtils {
+
+    public static final String AUGMENT_IDENTIFIER = "augment-identifier";
+
+
+    public YangSchemaUtils() {
+        throw new UnsupportedOperationException("Helper class. Instantiation is prohibited");
+    }
+
+
+    public static QName getAugmentationQName(AugmentationSchema augmentation) {
+        Preconditions.checkNotNull(augmentation, "Augmentation must not be null.");
+        QName identifier = getAugmentationIdentifier(augmentation);
+        if(identifier != null) {
+            return identifier;
+        }
+        for(DataSchemaNode child : augmentation.getChildNodes()) {
+            // FIXME: Return true name
+            return QName.create(child.getQName(), "foo_augment");
+        }
+        // FIXME: Allways return a qname with module namespace.
+        return null;
+    }
+
+    public static QName getAugmentationIdentifier(AugmentationSchema augmentation) {
+        for(UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
+            if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) {
+                return extension.getQName();
+            }
+        }
+        return null;
+    }
+}
index 9f3a6e8..c67a017 100644 (file)
@@ -51,7 +51,7 @@ public abstract class AbstractDataServiceTest {
     protected ListeningExecutorService executor;
     protected BindingIndependentDataServiceConnector connectorServiceImpl;
     protected HashMapDataStore rawDataStore;
-    private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+    protected SchemaAwareDataStoreAdapter schemaAwareDataStore;
     private DataStoreStatsWrapper dataStoreStats;
 
     protected DataStore dataStore;
@@ -137,15 +137,15 @@ public abstract class AbstractDataServiceTest {
     @After
     public void afterTest() {
 
-        log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+        log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
                 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
                 dataStoreStats.getConfigurationReadAverageTime());
 
-        log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+        log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
                 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
                 dataStoreStats.getOperationalReadAverageTime());
 
-        log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+        log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
                 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
                 dataStoreStats.getRequestCommitAverageTime());
 
index f60ddb9..5a98767 100644 (file)
@@ -10,6 +10,7 @@ import java.util.concurrent.Executors;
 
 
 
+
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
@@ -28,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -148,7 +150,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         assertEquals(TransactionStatus.COMMITED, ret2.getResult());
 
         // Data are not in the store.
-        assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
+        assertNull(baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA));
 
     }
 
@@ -169,11 +171,13 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         flow.setNode(NODE_REF);
         InstructionsBuilder instructions = new InstructionsBuilder();
         InstructionBuilder instruction = new InstructionBuilder();
+        
+        instruction.setOrder(10);
         ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
         List<Action> actionList = new ArrayList<>();
         PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
         popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build());
+        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(10).build());
 
         applyActions.setAction(actionList );
         
@@ -200,17 +204,9 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         FlowBuilder flow = new FlowBuilder();
         flow.setKey(key);
         MatchBuilder match = new MatchBuilder();
-        Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
-        // ipv4Match.setIpv4Destination(new Ipv4Prefix(cliInput.get(4)));
         match.setLayer4Match(new TcpMatchBuilder().build());
         flow.setMatch(match.build());
-        DropAction dropAction = new DropActionBuilder().build();
-        //   ActionBuilder action = new ActionBuilder();
-
-        //  List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Action> actions = Collections
-             //   .singletonList(action.build());
-        //   flow.setAction(actions);
-        flow.setPriority(2);
+        
         System.out.println("Putting the configuration Data................");
         path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
        // DataObject cls = (DataObject) modification.readConfigurationData(path1);
index 4df10bc..85d484a 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 import static org.junit.Assert.*;
 
@@ -77,8 +78,10 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
                 return transaction.commit();
             }
         });
-        mappingServiceImpl.onGlobalContextUpdated(getContext(getAllModelFilenames()));
         
+        SchemaContext ctx = getContext(getAllModelFilenames());
+        schemaAwareDataStore.onGlobalContextUpdated(ctx);
+        mappingServiceImpl.onGlobalContextUpdated(ctx);
         RpcResult<TransactionStatus> result = future.get().get();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
         
index 2cd396d..91163d8 100644 (file)
@@ -97,9 +97,6 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
         
         
         testAddingNodeConnector();
-        
-        
-        
         testNodeRemove();
         
         
index 63368bd..7fe5f0c 100644 (file)
@@ -166,11 +166,12 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
         flow.setNode(NODE_REF);
         InstructionsBuilder instructions = new InstructionsBuilder();
         InstructionBuilder instruction = new InstructionBuilder();
+        instruction.setOrder(10);
         ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
         List<Action> actionList = new ArrayList<>();
         PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
         popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build());
+        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(0).build());
 
         applyActions.setAction(actionList );
         
index 7fb0580..47e9c61 100644 (file)
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index bee8633..fb3e38f 100644 (file)
@@ -10,8 +10,9 @@ import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.yangtools.concepts.Path;
 
-public abstract class AbstractDataModification<P /* extends Path<P> */, D> implements DataModification<P, D> {
+public abstract class AbstractDataModification<P extends Path<P>, D> implements DataModification<P, D> {
 
     private final ConcurrentMap<P, D> operationalOriginal;
     private final ConcurrentMap<P, D> configurationOriginal;
@@ -56,28 +57,28 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
         unmodifiable_operationalUpdate = Collections.unmodifiableMap(operationalUpdate);
         unmodifiable_configurationRemove = Collections.unmodifiableSet(configurationRemove.keySet());
         unmodifiable_OperationalRemove = Collections.unmodifiableSet(operationalRemove.keySet());
-
     }
 
     @Override
     public final void putConfigurationData(P path, D data) {
         checkMutable();
-
-        if (!hasConfigurationOriginal(path)) {
+        D original = null;
+        if ((original = getConfigurationOriginal(path)) == null) {
             configurationCreated.put(path, data);
         }
 
-        configurationUpdate.put(path, data);
+        configurationUpdate.put(path, mergeConfigurationData(path,original, data));
         configurationRemove.remove(path);
     }
 
     @Override
     public final void putOperationalData(P path, D data) {
         checkMutable();
-        if (!hasOperationalOriginal(path)) {
+        D original = null;
+        if ((original = getOperationalOriginal(path)) == null) {
             operationalCreated.put(path, data);
         }
-        operationalUpdate.put(path, data);
+        operationalUpdate.put(path, mergeOperationalData(path,original,data));
         operationalRemove.remove(path);
     }
 
@@ -89,7 +90,7 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
     @Override
     public final void removeOperationalData(P path) {
         checkMutable();
-        hasOperationalOriginal(path);
+        getOperationalOriginal(path);
         operationalUpdate.remove(path);
         operationalRemove.put(path, path);
     }
@@ -102,7 +103,7 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
     @Override
     public final void removeConfigurationData(P path) {
         checkMutable();
-        hasConfigurationOriginal(path);
+        getConfigurationOriginal(path);
         configurationUpdate.remove(path);
         configurationRemove.put(path, path);
     }
@@ -163,27 +164,37 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
         return reader.readConfigurationData(path);
     }
 
-    private boolean hasConfigurationOriginal(P path) {
-        if (configurationOriginal.containsKey(path)) {
-            return true;
+    private D getConfigurationOriginal(P path) {
+        D data = configurationOriginal.get(path);
+        if (data != null) {
+            return data;
         }
-        data = reader.readConfigurationData(path);
+        data = reader.readConfigurationData(path);
         if (data != null) {
             configurationOriginal.putIfAbsent(path, data);
-            return true;
+            return data;
         }
-        return false;
+        return null;
     }
 
-    private boolean hasOperationalOriginal(P path) {
-        if (operationalOriginal.containsKey(path)) {
-            return true;
+    private D getOperationalOriginal(P path) {
+        D data = operationalOriginal.get(path);
+        if (data != null) {
+            return data;
         }
-        data = reader.readOperationalData(path);
+        data = reader.readOperationalData(path);
         if (data != null) {
             operationalOriginal.putIfAbsent(path, data);
-            return true;
+            return data;
         }
-        return false;
+        return null;
+    }
+    
+    protected D mergeOperationalData(P path,D stored, D modified) {
+        return modified;
+    }
+    
+    protected D mergeConfigurationData(P path,D stored, D modified) {
+        return modified;
     }
 }
index d6b3c53..9e61473 100644 (file)
@@ -20,7 +20,7 @@ import com.google.common.collect.Multimap;
  * @param <P>
  * @param <D>
  */
-public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements DataReader<P, D> {
+public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> {
 
     Multimap<P, DataReaderRegistration<P, D>> configReaders = HashMultimap.create();
     Multimap<P, DataReaderRegistration<P, D>> operationalReaders = HashMultimap.create();
@@ -139,14 +139,15 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
             
             @Override
             public boolean apply(Entry<P, DataReaderRegistration<P, D>> input) {
-                final Path key = input.getKey();
-                return key.contains(path) || ((Path) path).contains(key);
+                final P key = input.getKey();
+                return key.contains(path) || ((P) path).contains(key);
             }
             
         };
     }
 
-    private class ConfigurationDataReaderRegistration<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+    @SuppressWarnings("hiding")
+    private class ConfigurationDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
 
         public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) {
             super(key, instance);
@@ -158,7 +159,8 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
         }
     }
 
-    private class OperationalDataReaderRegistration<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+    @SuppressWarnings("hiding")
+    private class OperationalDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
 
         public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) {
             super(key, instance);
@@ -170,7 +172,7 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
         }
     }
 
-    private abstract static class DataReaderRegistration<P extends Path<?>, D> extends
+    private abstract static class DataReaderRegistration<P extends Path<P>, D> extends
             AbstractObjectRegistration<DataReader<P, D>> {
 
         private final P key;
index a18e5a9..5f4f815 100644 (file)
@@ -28,8 +28,6 @@ import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRo
 import org.opendaylight.yangtools.concepts.Path
 import org.slf4j.LoggerFactory
 import java.util.HashSet
-import java.util.Map.Entry
-import java.util.Iterator
 import java.util.Collection
 import com.google.common.collect.FluentIterable;
 import java.util.Set
@@ -37,7 +35,6 @@ import com.google.common.collect.ImmutableList
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry
-import java.util.concurrent.atomic.AtomicLong
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
 
 abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
index 68f9506..83943a1 100644 (file)
@@ -5,8 +5,10 @@ import java.util.Set;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataChange;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.Path;
 
-public class DataChangeEventImpl<P, D> implements DataChangeEvent<P, D> {
+public class DataChangeEventImpl<P extends Path<P>, D> implements DataChangeEvent<P, D>, Immutable {
 
     private final DataChange<P, D> dataChange;
 
index 2764635..474d4b8 100644 (file)
@@ -5,15 +5,28 @@ import java.util.Map;
 import java.util.Set;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.Path;
 
-public class InitialDataChangeEventImpl<P,D> implements DataChangeEvent<P, D> {
+public class InitialDataChangeEventImpl<P extends Path<P>,D> implements DataChangeEvent<P, D>, Immutable {
 
-    private final D originalOperationalTree;
-    private final D originalConfigurationTree;
+    private final D updatedOperationalTree;
+    private final D updatedConfigurationTree;
+    private final Map<P,D> updatedConfigurationData;
+    private final Map<P,D> updatedOperationalData;
 
     public InitialDataChangeEventImpl(D configTree, D operTree) {
-        originalConfigurationTree = configTree;
-        originalOperationalTree = operTree;
+        updatedConfigurationTree = configTree;
+        updatedOperationalTree = operTree;
+        updatedConfigurationData = Collections.emptyMap();
+        updatedOperationalData = Collections.emptyMap();
+    }
+    
+    public InitialDataChangeEventImpl(D configTree, D operTree, Map<P, D> updatedCfgData, Map<P, D> updatedOperData) {
+        updatedConfigurationTree = configTree;
+        updatedOperationalTree = operTree;
+        updatedConfigurationData = updatedCfgData;
+        updatedOperationalData = updatedOperData;
     }
     
     @Override
@@ -44,31 +57,31 @@ public class InitialDataChangeEventImpl<P,D> implements DataChangeEvent<P, D> {
     }
     @Override
     public Map<P, D> getUpdatedConfigurationData() {
-        return Collections.emptyMap();
+        return updatedConfigurationData;
     }
     
     @Override
     public D getUpdatedConfigurationSubtree() {
-        return originalConfigurationTree;
+        return updatedConfigurationTree;
     }
     @Override
     public D getUpdatedOperationalSubtree() {
-        return originalOperationalTree;
+        return updatedOperationalTree;
     }
     
     @Override
     public D getOriginalConfigurationSubtree() {
-        return originalConfigurationTree;
+        return updatedConfigurationTree;
     }
     
     @Override
     public D getOriginalOperationalSubtree() {
-        return originalOperationalTree;
+        return updatedOperationalTree;
     }
     
     @Override
     public Map<P, D> getUpdatedOperationalData() {
-        return Collections.emptyMap();
+        return updatedOperationalData;
     }
     
 
index 14ab057..a6601ce 100644 (file)
             <artifactId>sal-common-util</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-data-impl</artifactId>
-            <version>0.5.9-SNAPSHOT</version>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-impl</artifactId>
             <artifactId>config-api</artifactId>
             <version>0.2.3-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-impl</artifactId>
index 54c94dc..da7cccb 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
 
 class BrokerConfigActivator implements AutoCloseable {
     
@@ -51,6 +52,8 @@ class BrokerConfigActivator implements AutoCloseable {
         wrappedStore = new SchemaAwareDataStoreAdapter();
         wrappedStore.changeDelegate(store);
         wrappedStore.setValidationEnabled(false);
+       
+        context.registerService(SchemaServiceListener,wrappedStore,emptyProperties)  
         
         dataService.registerConfigurationReader(ROOT, wrappedStore);
         dataService.registerCommitHandler(ROOT, wrappedStore);
index 531f9e8..efbd81c 100644 (file)
@@ -41,9 +41,9 @@ import com.google.common.collect.Sets;
 import static com.google.common.base.Preconditions.*;
 
 public class SchemaServiceImpl implements //
-SchemaService, //
-ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
-AutoCloseable {
+        SchemaService, //
+        ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
+        AutoCloseable {
     private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
 
     private ListenerRegistry<SchemaServiceListener> listeners;
@@ -61,7 +61,7 @@ AutoCloseable {
     private BundleTracker<Object> bundleTracker;
     private final YangStoreCache cache = new YangStoreCache();
 
-    private ServiceTracker<SchemaServiceListener,SchemaServiceListener> listenerTracker;
+    private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
 
     public ListenerRegistry<SchemaServiceListener> getListeners() {
         return listeners;
@@ -93,7 +93,7 @@ AutoCloseable {
         if (listeners == null) {
             listeners = new ListenerRegistry<>();
         }
-        
+
         listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, this);
         bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
         bundleTracker.open();
@@ -132,12 +132,11 @@ AutoCloseable {
         throw new UnsupportedOperationException();
     }
 
-    
     @Override
     public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
         return listeners.register(listener);
     }
-    
+
     @Override
     public void close() throws Exception {
         bundleTracker.close();
@@ -196,15 +195,15 @@ AutoCloseable {
 
     private void updateCache(SchemaContext snapshot) {
         cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
-        
+
         Object[] services = listenerTracker.getServices();
-        if(services != null) {
-            for(Object rawListener : services) {
+        if (services != null) {
+            for (Object rawListener : services) {
                 SchemaServiceListener listener = (SchemaServiceListener) rawListener;
                 try {
                     listener.onGlobalContextUpdated(snapshot);
                 } catch (Exception e) {
-                    logger.error("Exception occured during invoking listener",e);
+                    logger.error("Exception occured during invoking listener", e);
                 }
             }
         }
@@ -212,7 +211,7 @@ AutoCloseable {
             try {
                 listener.getInstance().onGlobalContextUpdated(snapshot);
             } catch (Exception e) {
-                logger.error("Exception occured during invoking listener",e);
+                logger.error("Exception occured during invoking listener", e);
             }
         }
     }
@@ -243,7 +242,7 @@ AutoCloseable {
                     proposedNewState.putAll(inconsistentBundlesToYangURLs);
                     proposedNewState.putAll(bundle, addedURLs);
                     boolean adding = true;
-                    
+
                     if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
                         inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
                     }
@@ -301,23 +300,23 @@ AutoCloseable {
             this.cachedContextSnapshot = ctx;
         }
     }
-    
+
     @Override
     public SchemaServiceListener addingService(ServiceReference<SchemaServiceListener> reference) {
-        
+
         SchemaServiceListener listener = context.getService(reference);
         SchemaContext _ctxContext = getGlobalContext();
-        if(getContext() != null) {
+        if (getContext() != null) {
             listener.onGlobalContextUpdated(_ctxContext);
         }
         return listener;
     }
-    
+
     @Override
     public void modifiedService(ServiceReference<SchemaServiceListener> reference, SchemaServiceListener service) {
         // NOOP
     }
-    
+
     @Override
     public void removedService(ServiceReference<SchemaServiceListener> reference, SchemaServiceListener service) {
         context.ungetService(reference);
index 9116d50..0d2d1c8 100644 (file)
@@ -52,7 +52,7 @@ public class DataStoreStatsWrapper implements Delegator<DataStore>, DataStore {
         } finally {
             final long endTime = System.nanoTime();
             final long runTime = endTime - startTime;
-            cfgReadTimeTotal.addAndGet(runTime);
+            operReadTimeTotal.addAndGet(runTime);
         }
     }
 
@@ -98,40 +98,40 @@ public class DataStoreStatsWrapper implements Delegator<DataStore>, DataStore {
         return requestCommitCount.get();
     }
 
-    public final long getConfigurationReadTotalTime() {
-        return cfgReadTimeTotal.get();
+    public final double getConfigurationReadTotalTime() {
+        return cfgReadTimeTotal.get() / 1000.0d;
     }
 
-    public final long getOperationalReadTotalTime() {
-        return operReadTimeTotal.get();
+    public final double getOperationalReadTotalTime() {
+        return operReadTimeTotal.get() / 1000.0d;
     }
 
-    public final long getRequestCommitTotalTime() {
-        return requestCommitTimeTotal.get();
+    public final double getRequestCommitTotalTime() {
+        return requestCommitTimeTotal.get() / 1000.0d;
     }
 
-    public final long getConfigurationReadAverageTime() {
+    public final double getConfigurationReadAverageTime() {
         long readCount = cfgReadCount.get();
         if(readCount == 0) {
             return 0;
         }
-        return cfgReadTimeTotal.get() / readCount;
+        return getConfigurationReadTotalTime() / readCount;
     }
 
-    public final long getOperationalReadAverageTime() {
+    public final double getOperationalReadAverageTime() {
         long readCount = operReadCount.get();
         if(readCount == 0) {
             return 0;
         }
-        return operReadTimeTotal.get() / readCount;
+        return getOperationalReadTotalTime() / readCount;
     }
 
-    public final long getRequestCommitAverageTime() {
+    public final double getRequestCommitAverageTime() {
         long count = requestCommitCount.get();
         if(count == 0) {
             return 0;
         }
-        return requestCommitTimeTotal.get() / count;
+        return getRequestCommitTotalTime() / count;
     }
 
 }
index d67697f..d8680ce 100644 (file)
@@ -12,9 +12,9 @@ import java.util.concurrent.ConcurrentHashMap
 import java.util.Set
 import java.util.Collections
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
-import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
 import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry
 
 class RpcRouterImpl implements RpcRouter, Identifiable<String> {
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend
deleted file mode 100644 (file)
index 8cdbf92..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker.impl
-
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-
-class SchemaAwareDataMerger {
-
-    private SchemaContext schema;
-    
-    
-    
-    
-}
\ No newline at end of file
index 1f90814..4f4fadc 100644 (file)
@@ -5,23 +5,35 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
 import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator;
 import org.opendaylight.controller.sal.core.api.data.DataStore;
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
 import org.opendaylight.yangtools.yang.common.QName;
+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.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.util.YangDataOperations;
+import org.opendaylight.yangtools.yang.util.YangSchemaUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,6 +41,7 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.FluentIterable;
 
 import static com.google.common.base.Preconditions.*;
+import org.opendaylight.yangtools.yang.util.YangDataOperations;
 
 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
         DataStore, //
@@ -39,7 +52,6 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     private SchemaContext schema = null;
     private boolean validationEnabled = false;
-    private SchemaAwareDataMerger dataMerger = null;
     private DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
 
     @Override
@@ -100,7 +112,8 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
             DataModification<InstanceIdentifier, CompositeNode> modification) {
         validateAgainstSchema(modification);
-        DataModification<InstanceIdentifier, CompositeNode> cleanedUp = prepareMergedTransaction(modification);
+        NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
+        cleanedUp.status = TransactionStatus.SUBMITED;
         return retrieveDelegate().requestCommit(cleanedUp);
     }
 
@@ -138,10 +151,39 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         this.schema = null;
     }
 
-    private DataModification<InstanceIdentifier, CompositeNode> prepareMergedTransaction(
+    protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified, boolean config) {
+        long startTime = System.nanoTime();
+        try {
+        DataSchemaNode node = schemaNodeFor(path);
+        return YangDataOperations.merge(node,stored,modified,config);
+        } finally {
+            //System.out.println("Merge time: " + ((System.nanoTime() - startTime) / 1000.0d));
+        }
+    }
+    
+    
+    private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
+        checkState(schema != null,"YANG Schema is not available");
+        return YangSchemaUtils.getSchemaNode(schema, path);
+    }
+
+    private NormalizedDataModification prepareMergedTransaction(
             DataModification<InstanceIdentifier, CompositeNode> original) {
         // NOOP for now
-        return 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());
+        }
+        for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
+            normalized.removeConfigurationData(entry);
+        }
+        for(InstanceIdentifier entry : original.getRemovedOperationalData()) {
+            normalized.removeOperationalData(entry);
+        }
+        return normalized;
     }
 
     private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
@@ -242,4 +284,44 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
     }
+    
+    private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
+
+        private Object identifier;
+        private TransactionStatus status;
+
+        public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
+            super(getDelegate());
+            identifier = original;
+            status = TransactionStatus.NEW;
+        }
+        
+        @Override
+        public Object getIdentifier() {
+            return this.identifier;
+        }
+        
+        @Override
+        public TransactionStatus getStatus() {
+            return status;
+        }
+
+        @Override
+        public Future<RpcResult<TransactionStatus>> commit() {
+            throw new UnsupportedOperationException("Commit should not be invoked on this");
+        }
+        
+        @Override
+        protected CompositeNode mergeConfigurationData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
+            return mergeData(path,stored, modified,true);
+        }
+        
+        @Override
+        protected CompositeNode mergeOperationalData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
+            // TODO Auto-generated method stub
+            return mergeData(path,stored,modified,false);
+        }
+        
+    }
+
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend
new file mode 100644 (file)
index 0000000..f69e00a
--- /dev/null
@@ -0,0 +1,116 @@
+package org.opendaylight.yangtools.yang.util
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import static com.google.common.base.Preconditions.*;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.util.ArrayList
+
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import java.util.List
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import java.util.Collections
+import static extension org.opendaylight.yangtools.yang.util.YangDataUtils.*;
+import java.util.HashSet
+import org.opendaylight.yangtools.yang.common.QName
+
+class YangDataOperations {
+
+    static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) {
+        checkConfigurational(schema, config);
+        if (stored === null) {
+            return modified;
+        }
+
+        if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) {
+            return mergeContainer(schema as DataNodeContainer, stored, modified, config);
+        }
+        throw new IllegalArgumentException("Supplied node is not data node container.");
+    }
+
+    private def static checkConfigurational(DataSchemaNode node, boolean config) {
+        if (config) {
+            checkArgument(node.configuration, "Supplied composite node is not configurational.");
+        }
+    }
+
+    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
+        List<Node<?>> modified, boolean configurational) {
+        checkArgument(original.size === 1);
+        checkArgument(modified.size === 1);
+        checkConfigurational(node, configurational);
+        return modified;
+    }
+
+    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
+        List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
+        return modified;
+    }
+
+    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
+        List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
+        checkArgument(original.size === 1);
+        checkArgument(modified.size === 1);
+        return Collections.singletonList(
+            merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational));
+    }
+
+    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
+        List<Node<?>> modified, boolean configurational) {
+        checkConfigurational(node,configurational);
+        if(node.keyDefinition === null || node.keyDefinition.empty) {
+            return modified;
+        } 
+        val originalMap = (original as List).toIndexMap(node.keyDefinition);
+        val modifiedMap = (modified as List).toIndexMap(node.keyDefinition);
+        
+        val List<Node<?>> mergedNodes = new ArrayList(original.size + modified.size);
+        for(entry : modifiedMap.entrySet) {
+            val originalEntry = originalMap.get(entry.key);
+            if(originalEntry != null) {
+                originalMap.remove(entry.key);
+                mergedNodes.add(merge(node,originalEntry,entry.value,configurational));
+                
+            }
+        }
+        mergedNodes.addAll(originalMap.values);
+        return mergedNodes;
+    }
+
+    static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
+        CompositeNode modified, boolean config) {
+        if (stored == null) {
+            return modified;
+        }
+        checkNotNull(stored)
+        checkNotNull(modified)
+        checkArgument(stored.nodeType == modified.nodeType);
+
+        val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
+        
+        val toProcess = new HashSet<QName>(stored.keySet);
+        toProcess.addAll(modified.keySet);
+        
+        for (qname : toProcess) {
+            val schemaChild = schema.getDataChildByName(qname);
+            val storedChildren = stored.get(qname);
+            val modifiedChildren = modified.get(qname);
+
+            if (modifiedChildren !== null && !modifiedChildren.empty) {
+                if (storedChildren === null || storedChildren.empty || schemaChild === null) {
+                    mergedChildNodes.addAll(modifiedChildren);
+                } else {
+                    mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
+                }
+            } else if (storedChildren !== null && !storedChildren.empty) {
+                mergedChildNodes.addAll(storedChildren);
+            }
+        }
+        return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java
new file mode 100644 (file)
index 0000000..687e4d9
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.yangtools.yang.util;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+import static com.google.common.base.Preconditions.*;
+
+public class YangDataUtils {
+
+    public YangDataUtils() {
+        // TODO Auto-generated constructor stub
+    }
+
+    
+    
+    public static Map<Map<QName,Object>,CompositeNode> toIndexMap(List<CompositeNode> nodes,List<QName> keys) {
+        ConcurrentHashMap<Map<QName,Object>,CompositeNode> ret = new ConcurrentHashMap<>();
+        for(CompositeNode node : nodes) {
+            Map<QName, Object> key = getKeyMap(node,keys);
+            ret.put(key, node);
+        }
+        return ret;
+    }
+
+
+
+    public static Map<QName,Object> getKeyMap(CompositeNode node, List<QName> keys) {
+        Map<QName,Object> map = new HashMap<>();
+        for(QName key : keys) {
+            SimpleNode<?> keyNode = node.getFirstSimpleByName(QName.create(node.getNodeType(), key.getLocalName()));
+            checkArgument(keyNode != null,"Node must contains all keys.");
+            Object value = keyNode.getValue();
+            map.put(key, value);
+            
+        }
+        return map;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java
new file mode 100644 (file)
index 0000000..44ee2a3
--- /dev/null
@@ -0,0 +1,239 @@
+package org.opendaylight.yangtools.yang.util;
+
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.YangNode;
+
+import static com.google.common.base.Preconditions.*;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+public class YangSchemaUtils {
+
+    private static final Function<PathArgument, QName> QNAME_FROM_PATH_ARGUMENT = new Function<PathArgument, QName>(){
+        
+        @Override
+        public QName apply(PathArgument input) {
+            if(input == null) {
+                return null;
+            }
+            return input.getNodeType();
+        }
+    };
+
+    private  YangSchemaUtils() {
+        throw new UnsupportedOperationException("Utility class.");
+    }
+    
+    
+    public static DataSchemaNode getSchemaNode(SchemaContext schema,InstanceIdentifier path) {
+        checkArgument(schema != null,"YANG Schema must not be null.");
+        checkArgument(path != null,"Path must not be null.");
+        return getSchemaNode(schema, FluentIterable.from(path.getPath()).transform(QNAME_FROM_PATH_ARGUMENT));
+    }
+    
+    public static DataSchemaNode getSchemaNode(SchemaContext schema,Iterable<QName> path) {
+        checkArgument(schema != null,"YANG Schema must not be null.");
+        checkArgument(path != null,"Path must not be null.");
+        if(!path.iterator().hasNext()){
+            return toRootDataNode(schema);
+        }
+        
+        QName firstNode = path.iterator().next();
+        DataNodeContainer previous = schema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
+                firstNode.getRevision());
+        Iterator<QName> iterator = path.iterator();
+        
+        while (iterator.hasNext()) {
+            checkArgument(previous!= null, "Supplied path does not resolve into valid schema node.");
+            QName arg = iterator.next();
+            DataSchemaNode currentNode = previous.getDataChildByName(arg);
+            if (currentNode == null && previous instanceof DataNodeContainer) {
+                currentNode = searchInChoices(previous, arg);
+            }
+            if (currentNode instanceof DataNodeContainer) {
+                previous = (DataNodeContainer) currentNode;
+            } else if (currentNode instanceof LeafSchemaNode || currentNode instanceof LeafListSchemaNode) {
+                checkArgument(!iterator.hasNext(), "Path nests inside leaf node, which is not allowed.");
+                return currentNode;
+            }
+        }
+        return (DataSchemaNode) previous;
+    }
+    
+
+    private static DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) {
+        Set<DataSchemaNode> children = node.getChildNodes();
+        for (DataSchemaNode child : children) {
+            if (child instanceof ChoiceNode) {
+                ChoiceNode choiceNode = (ChoiceNode) child;
+                DataSchemaNode potential = searchInCases(choiceNode, arg);
+                if (potential != null) {
+                    return potential;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) {
+        Set<ChoiceCaseNode> cases = choiceNode.getCases();
+        for (ChoiceCaseNode caseNode : cases) {
+            DataSchemaNode node = caseNode.getDataChildByName(arg);
+            if (node != null) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    private static ContainerSchemaNode toRootDataNode(SchemaContext schema) {
+        return new NetconfDataRootNode(schema);
+    }
+
+    private static final class NetconfDataRootNode implements ContainerSchemaNode {
+    
+        public NetconfDataRootNode(SchemaContext schema) {
+            // TODO Auto-generated constructor stub
+        }
+
+        @Override
+        public YangNode getParent() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Set<TypeDefinition<?>> getTypeDefinitions() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Set<DataSchemaNode> getChildNodes() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Set<GroupingDefinition> getGroupings() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public DataSchemaNode getDataChildByName(QName name) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public DataSchemaNode getDataChildByName(String name) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Set<UsesNode> getUses() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Set<AugmentationSchema> getAvailableAugmentations() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public boolean isAugmenting() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+    
+        @Override
+        public boolean isAddedByUses() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+    
+        @Override
+        public boolean isConfiguration() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+    
+        @Override
+        public ConstraintDefinition getConstraints() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public QName getQName() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public SchemaPath getPath() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public String getDescription() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public String getReference() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public Status getStatus() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    
+        @Override
+        public boolean isPresenceContainer() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+    
+    }
+
+}