Merge "Fixed performance issues with implementation of BA-to-BI mapping"
authorEd Warnicke <eaw@cisco.com>
Thu, 14 Nov 2013 12:36:13 +0000 (12:36 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 14 Nov 2013 12:36:13 +0000 (12:36 +0000)
15 files changed:
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeGenerator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/ClassGenerator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/FieldGenerator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/JavassistUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/MethodGenerator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CompositeNodeUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RuntimeGeneratedMappingServiceImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java

index 35264e7..9e4d3a5 100644 (file)
@@ -88,6 +88,7 @@
                             org.opendaylight.controller.sal.binding.impl.*,
                             org.opendaylight.controller.sal.binding.codegen,
                             org.opendaylight.controller.sal.binding.codegen.*,
+                            org.opendaylight.controller.sal.binding.dom.*,
                         </Private-Package>
                     </instructions>
                 </configuration>
index 1d82807..6672d95 100644 (file)
@@ -7,11 +7,9 @@
  */
 package org.opendaylight.controller.sal.binding.codegen;
 
-import org.opendaylight.controller.sal.binding.spi.DelegateProxy;
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
 import org.opendaylight.controller.sal.binding.spi.RpcRouter;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcImplementation;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java
deleted file mode 100644 (file)
index c6be284..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.codegen.impl;
-
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtMethod;
-
-public class JavassistUtils {
-
-    public static interface ClassGenerator {
-        void process(CtClass cls);
-    }
-
-    public static interface MethodGenerator {
-        void process(CtMethod method);
-    }
-
-    public static interface FieldGenerator {
-        void process(CtField field);
-    }
-}
index ea6dc13..93c192c 100644 (file)
@@ -12,9 +12,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService
 
 import javassist.CtClass
 import static com.google.common.base.Preconditions.*
-
-import javassist.CtField
-import javassist.Modifier
 import javassist.CtMethod
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
@@ -22,13 +19,11 @@ import org.opendaylight.yangtools.yang.binding.BaseIdentity
 
 import java.util.Map
 import java.util.HashMap
-import javassist.NotFoundException
-import javassist.LoaderClassPath
-import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.MethodGenerator
-import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.ClassGenerator
+
+
 import org.opendaylight.yangtools.yang.binding.NotificationListener
 import org.opendaylight.yangtools.yang.binding.Notification
-import java.util.Arrays
+
 
 import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
@@ -39,19 +34,21 @@ import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.No
 import java.util.Set
 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper
 import java.util.WeakHashMap
-import javassist.ClassClassPath
 import org.opendaylight.yangtools.yang.binding.annotations.QName
 import org.opendaylight.yangtools.yang.binding.DataContainer
 import org.opendaylight.yangtools.yang.binding.RpcImplementation
+import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
 
 class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
 
     val CtClass BROKER_NOTIFICATION_LISTENER;
     val ClassPool classPool;
+    val extension JavassistUtils utils;
     val Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses;
 
     public new(ClassPool pool) {
         classPool = pool;
+        utils = new JavassistUtils(pool);
         invokerClasses = new WeakHashMap();
         BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass;
     }
@@ -216,65 +213,9 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
             finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener>);
     }
 
-    private def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
-        val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
-        function1.process(method);
-        it.addMethod(method);
-    }
-
-    private def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) {
-        for (method : source.methods) {
-            if (method.declaringClass == source) {
-                val redeclaredMethod = new CtMethod(method, target, null);
-                function1.process(redeclaredMethod);
-                target.addMethod(redeclaredMethod);
-            }
-        }
-    }
-
-    private def CtClass createClass(String fqn, ClassGenerator cls) {
-        val target = classPool.makeClass(fqn);
-        cls.process(target);
-        return target;
-    }
-
-    private def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) {
-        val target = classPool.makeClass(fqn);
-        target.implementsType(superInterface);
-        cls.process(target);
-        return target;
-    }
-
-    private def void implementsType(CtClass it, CtClass supertype) {
-        checkArgument(supertype.interface, "Supertype must be interface");
-        addInterface(supertype);
-    }
-
-    private def asCtClass(Class<?> class1) {
-        classPool.get(class1);
-    }
+    
 
-    private def CtField field(CtClass it, String name, Class<?> returnValue) {
-        val field = new CtField(returnValue.asCtClass, name, it);
-        field.modifiers = Modifier.PUBLIC
-        addField(field);
-        return field;
-    }
 
-    def get(ClassPool pool, Class<?> cls) {
-        try {
-            return pool.get(cls.name)
-        } catch (NotFoundException e) {
-            pool.appendClassPath(new LoaderClassPath(cls.classLoader));
-            try {
-                return pool.get(cls.name)
-
-            } catch (NotFoundException ef) {
-                pool.appendClassPath(new ClassClassPath(cls));
-                return pool.get(cls.name)
-            }
-        }
-    }
 
     protected def resolveInvokerClass(Class<? extends NotificationListener> class1) {
         val invoker = invokerClasses.get(class1);
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/ClassGenerator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/ClassGenerator.java
new file mode 100644 (file)
index 0000000..c4abc32
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.codegen.util;
+
+import javassist.CtClass;
+
+public interface ClassGenerator {
+    void process(CtClass cls);
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/FieldGenerator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/FieldGenerator.java
new file mode 100644 (file)
index 0000000..2e053f0
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.codegen.util;
+
+import javassist.CtField;
+
+public interface FieldGenerator {
+    void process(CtField field);
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/JavassistUtils.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/JavassistUtils.xtend
new file mode 100644 (file)
index 0000000..19737b8
--- /dev/null
@@ -0,0 +1,94 @@
+package org.opendaylight.controller.sal.binding.codegen.util
+
+import javassist.CtClass
+import javassist.CtMethod
+import javassist.ClassPool
+import java.util.Arrays
+import static com.google.common.base.Preconditions.*;
+import javassist.CtField
+import javassist.Modifier
+import javassist.NotFoundException
+import javassist.LoaderClassPath
+import javassist.ClassClassPath
+
+class JavassistUtils {
+
+    ClassPool classPool
+
+    new(ClassPool pool) {
+        classPool = pool;
+    }
+
+    def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
+        val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
+        function1.process(method);
+        it.addMethod(method);
+    }
+    
+        def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter1, Class<?> parameter2,  MethodGenerator function1) {
+        val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter1.asCtClass,parameter2.asCtClass), it);
+        function1.process(method);
+        it.addMethod(method);
+    }
+    
+    
+    def void staticMethod(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
+        val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
+        function1.process(method);
+        it.addMethod(method);
+    }
+
+    def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) {
+        for (method : source.methods) {
+            if (method.declaringClass == source) {
+                val redeclaredMethod = new CtMethod(method, target, null);
+                function1.process(redeclaredMethod);
+                target.addMethod(redeclaredMethod);
+            }
+        }
+    }
+
+    def CtClass createClass(String fqn, ClassGenerator cls) {
+        val target = classPool.makeClass(fqn);
+        cls.process(target);
+        return target;
+    }
+
+    def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) {
+        val target = classPool.makeClass(fqn);
+        target.implementsType(superInterface);
+        cls.process(target);
+        return target;
+    }
+
+    def void implementsType(CtClass it, CtClass supertype) {
+        checkArgument(supertype.interface, "Supertype must be interface");
+        addInterface(supertype);
+    }
+
+    def asCtClass(Class<?> class1) {
+        classPool.get(class1);
+    }
+
+    def CtField field(CtClass it, String name, Class<?> returnValue) {
+        val field = new CtField(returnValue.asCtClass, name, it);
+        field.modifiers = Modifier.PUBLIC
+        addField(field);
+        return field;
+    }
+
+    def get(ClassPool pool, Class<?> cls) {
+        try {
+            return pool.get(cls.name)
+        } catch (NotFoundException e) {
+            pool.appendClassPath(new LoaderClassPath(cls.classLoader));
+            try {
+                return pool.get(cls.name)
+
+            } catch (NotFoundException ef) {
+                pool.appendClassPath(new ClassClassPath(cls));
+                return pool.get(cls.name)
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/MethodGenerator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/MethodGenerator.java
new file mode 100644 (file)
index 0000000..0eddbd6
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.codegen.util;
+
+import javassist.CtMethod;
+
+public interface MethodGenerator {
+    void process(CtMethod method);
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend
new file mode 100644 (file)
index 0000000..2d67f11
--- /dev/null
@@ -0,0 +1,776 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import javassist.ClassPool
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
+import javassist.CtClass
+import java.util.Map
+import org.opendaylight.yangtools.yang.common.QName
+import javassist.CtField
+import static javassist.Modifier.*
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import java.util.HashMap
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import java.util.WeakHashMap
+import java.util.List
+import java.util.TreeSet
+import com.google.common.base.Joiner
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*;
+import org.opendaylight.yangtools.yang.binding.BindingDeserializer
+import org.opendaylight.yangtools.yang.binding.BindingSerializer
+import org.opendaylight.yangtools.yang.binding.BindingCodec
+import org.slf4j.LoggerFactory
+
+class TransformerGenerator {
+
+    private static val log = LoggerFactory.getLogger(TransformerGenerator)
+
+    public static val STRING = Types.typeForClass(String);
+    public static val BOOLEAN = Types.typeForClass(Boolean);
+    public static val INTEGER = Types.typeForClass(Integer);
+
+    //public static val DECIMAL = Types.typeForClass(Decimal);
+    public static val LONG = Types.typeForClass(Long);
+
+    val ClassPool classPool
+    val extension JavassistUtils utils;
+
+    CtClass ctTransformator
+
+    CtClass ctQName
+
+    @Property
+    var Map<Type, Type> typeDefinitions;
+
+    @Property
+    var Map<Type, GeneratedTypeBuilder> typeToDefinition
+
+    @Property
+    var Map<Type, SchemaNode> typeToSchemaNode
+
+    val Map<Class<?>, Class<?>> generatedClasses = new WeakHashMap();
+
+    public new(ClassPool pool) {
+        classPool = pool;
+        utils = new JavassistUtils(pool)
+
+        ctTransformator = BindingCodec.asCtClass;
+        ctQName = QName.asCtClass
+    }
+
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
+        return withClassLoader(inputType.classLoader) [ |
+            val ret = generatedClasses.get(inputType);
+            if (ret !== null) {
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ref = Types.typeForClass(inputType)
+            val node = typeToSchemaNode.get(ref)
+            val typeSpecBuilder = typeToDefinition.get(ref)
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateTransformerFor(inputType, typeSpec, node)
+            generatedClasses.put(inputType, newret);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
+        return withClassLoader(inputType.classLoader) [ |
+            val transformer = generatedClasses.get(inputType);
+            if (transformer != null) {
+                return transformer;
+            }
+            val newret = generateKeyTransformerFor(inputType, type, schema);
+            generatedClasses.put(inputType, newret);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
+        val cls = loadClassWithTCCL(type.resolvedName + "Key");
+        keyTransformerFor(cls, type, node);
+    }
+
+    private def serializer(Type type) {
+        val cls = loadClassWithTCCL(type.resolvedName);
+        transformerFor(cls);
+
+    }
+
+    def Class<?> getValueSerializer(GeneratedTransferObject type) {
+        val cls = loadClassWithTCCL(type.resolvedName);
+        val transformer = generatedClasses.get(cls);
+        if (transformer !== null) {
+            return transformer;
+        }
+        val valueTransformer = generateValueTransformer(cls, type);
+        generatedClasses.put(cls, valueTransformer);
+        return valueTransformer;
+    }
+
+    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.transformatorFqn) [
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                staticQNameField(node.QName);
+                implementsType(ctTransformator)
+                method(Object, "toDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                        
+                            return null;
+                        }
+                    '''
+                ]
+                method(Object, "fromDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            if($2 == null){
+                                return  null;
+                            }
+                            «QName.name» _localQName = $1;
+                            java.util.Map _compositeNode = (java.util.Map) $2;
+                            «FOR key : node.keyDefinition»
+                                «val propertyName = key.getterName»
+                                «val keyDef = node.getDataChildByName(key)»
+                                «val property = properties.get(propertyName)»
+                                «deserializeProperty(keyDef, property.returnType, property)»;
+                            «ENDFOR»
+                            «inputType.name» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
+                            return _value;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        return toDomStatic(QNAME,$1);
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''
+                        return fromDomStatic(QNAME,$1);
+                    '''
+                ]
+            ]
+            val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
+            val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+    private def <D> Class<? extends BindingCodec<Map<QName, Object>, D>> generateTransformerFor(Class<D> inputType,
+        GeneratedType typeSpec, SchemaNode node) {
+        try {
+            log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
+            val ctCls = createClass(typeSpec.transformatorFqn) [
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                staticQNameField(inputType);
+                implementsType(ctTransformator)
+                method(Object, "toDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = serializeBodyFacade(typeSpec, node)
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        return toDomStatic(QNAME,$1);
+                    '''
+                ]
+                method(Object, "fromDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = deserializeBody(typeSpec, node)
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''
+                        return fromDomStatic(QNAME,$1);
+                    '''
+                ]
+            ]
+
+            val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, D>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
+            val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+    private def keyConstructorList(List<QName> qnames) {
+        val names = new TreeSet<String>()
+        for (name : qnames) {
+            val fieldName = name.getterName;
+            names.add(fieldName);
+        }
+        return Joiner.on(",").join(names);
+    }
+
+    private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
+        val ret = serializeBody(type, node);
+        return ret;
+    }
+
+    private def String deserializeBody(GeneratedType type, SchemaNode node) {
+        val ret = deserializeBodyImpl(type, node);
+        return ret;
+    }
+
+    private def deserializeKey(GeneratedType type, ListSchemaNode node) {
+        if (node.keyDefinition != null && !node.keyDefinition.empty) {
+            return '''
+                «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
+                _builder.setKey(getKey);
+            ''';
+        }
+    }
+
+    private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
+        {
+            «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+            
+            if($2 == null) {
+                return null;
+            }
+            java.util.Map _compositeNode = (java.util.Map) $2;
+            «type.builderName» _builder = new «type.builderName»();
+            
+            return _builder.build();
+        }
+    '''
+
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
+        {
+            «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+            if($2 == null) {
+                return null;
+            }
+            java.util.Map _compositeNode = (java.util.Map) $2;
+            «type.builderName» _builder = new «type.builderName»();
+            «deserializeKey(type, node)»
+            «deserializeDataNodeContainerBody(type, node)»
+            return _builder.build();
+        }
+    '''
+
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
+        {
+            «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+            if($2 == null) {
+                return null;
+            }
+            java.util.Map _compositeNode = (java.util.Map) $2;
+            «type.builderName» _builder = new «type.builderName»();
+            «deserializeDataNodeContainerBody(type, node)»
+            return _builder.build();
+        }
+    '''
+
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
+        {
+            «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+            if($2 == null) {
+                return null;
+            }
+            java.util.Map _compositeNode = (java.util.Map) $2;
+            «type.builderName» _builder = new «type.builderName»();
+            «deserializeDataNodeContainerBody(type, node)»
+            return _builder.build();
+        }
+    '''
+
+    private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
+        deserializeNodeContainerBodyImpl(type, type.allProperties, node);
+    }
+
+    private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, MethodSignature> properties,
+        DataNodeContainer node) {
+        val ret = '''
+            «FOR child : node.childNodes.filter[!augmenting]»
+                «val signature = properties.get(child.getterName)»
+                «deserializeProperty(child, signature.returnType, signature)»
+                _builder.«signature.name.toSetter»(«signature.name»);
+            «ENDFOR»
+        '''
+        return ret;
+    }
+
+    private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
+        MethodSignature property) '''
+        java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+            localName»"));
+        //System.out.println("«property.name»#deCode"+_dom_«property.name»);
+        java.util.List «property.name» = new java.util.ArrayList();
+        if(_dom_«property.name» != null) {
+            java.util.List _serialized = new java.util.ArrayList();
+            java.util.Iterator _iterator = _dom_«property.name».iterator();
+            boolean _hasNext = _iterator.hasNext();
+            while(_hasNext) {
+                Object _listItem = _iterator.next();
+                //System.out.println("  item" + _listItem);
+                Object _value = «type.actualTypeArguments.get(0).serializer.name».fromDomStatic(_localQName,_listItem);
+                //System.out.println("  value" + _value);
+                «property.name».add(_value);
+                _hasNext = _iterator.hasNext();
+            }
+        }
+        
+        //System.out.println(" list" + «property.name»);
+    '''
+
+    private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
+        MethodSignature property) '''
+        java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+            localName»"));
+        java.util.List «property.name» = new java.util.ArrayList();
+        if(_dom_«property.name» != null) {
+            java.util.List _serialized = new java.util.ArrayList();
+            java.util.Iterator _iterator = _dom_«property.name».iterator();
+            boolean _hasNext = _iterator.hasNext();
+            while(_hasNext) {
+                Object _listItem = _iterator.next();
+                if(_listItem instanceof java.util.Map.Entry) {
+                    Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
+                    Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
+                    «property.name».add(_value);
+                }
+                _hasNext = _iterator.hasNext();
+            }
+        }
+    '''
+
+    private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) '''
+        java.util.List _dom_«property.name»_list = 
+            _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
+        «type.resolvedName» «property.name» = null;
+        if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) {
+            java.util.Map.Entry _dom_«property.name» = (java.util.Map.Entry) _dom_«property.name»_list.get(0);
+            Object _inner_value = _dom_«property.name».getValue();
+            «property.name» = «deserializeValue(type, "_inner_value")»;
+        }
+    '''
+
+    private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
+        MethodSignature property) '''
+        java.util.List _dom_«property.name»_list = 
+            _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
+        «type.resolvedName» «property.name» = null;
+        if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) {
+            
+            java.util.Map _dom_«property.name» = (java.util.Map) _dom_«property.name»_list.get(0);
+            «type.resolvedName» «property.name» =  «type.serializer.name».fromDomStatic(_localQName,_dom_«property.name»);
+        }
+    '''
+
+    private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
+        («type.resolvedName») «type.valueSerializer.name».fromDomValue(«domParameter»);
+    '''
+
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, GeneratedTransferObject typeSpec) {
+        try {
+
+            val returnType = typeSpec.valueReturnType;
+            if (returnType == null) {
+
+                val ctCls = createDummyImplementation(inputType, typeSpec);
+                val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ctCls = createClass(typeSpec.transformatorFqn) [
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                implementsType(ctTransformator)
+                implementsType(BindingDeserializer.asCtClass)
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
+                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            «returnType.resolvedName» _value =  _encapsulatedValue.getValue();
+                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+                            return _value;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        {
+                            return toDomValue($1);
+                        }
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            «returnType.name» _simpleValue = «deserializeValue(returnType, "$1")»;
+                            «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
+                            return _value;
+                        }
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''{
+                            return fromDomValue($1);
+                    }
+                    '''
+                ]
+            ]
+
+            val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
+            val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+
+    }
+
+    private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
+        log.info("Generating Dummy DOM Codec for {} with {}",object,object.classLoader)
+        return createClass(typeSpec.transformatorFqn) [
+            //staticField(Map,"AUGMENTATION_SERIALIZERS");
+            implementsType(ctTransformator)
+            implementsType(BindingDeserializer.asCtClass)
+            method(Object, "toDomValue", Object) [
+                modifiers = PUBLIC + FINAL + STATIC
+                body = '''return null;'''
+            ]
+            method(Object, "serialize", Object) [
+                body = '''
+                    {
+                        return toDomValue($1);
+                    }
+                '''
+            ]
+            method(Object, "fromDomValue", Object) [
+                modifiers = PUBLIC + FINAL + STATIC
+                body = '''return null;'''
+            ]
+            method(Object, "deserialize", Object) [
+                body = '''{
+                        return fromDomValue($1);
+                    }
+                    '''
+            ]
+        ]
+    }
+
+    def Type getValueReturnType(GeneratedTransferObject object) {
+        for (prop : object.properties) {
+            if (prop.name == "value") {
+                return prop.returnType;
+            }
+        }
+        if (object.superType != null) {
+            return getValueReturnType(object.superType);
+        }
+        return null;
+    }
+
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, Enumeration typeSpec) {
+        try {
+            log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
+            val ctCls = createClass(typeSpec.transformatorFqn) [
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                implementsType(ctTransformator)
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        if($1 == null) {
+                            return null;
+                        }
+                        «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+                        return _value.getValue();
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        return toDomValue($1);
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        if($1 == null) {
+                            return null;
+                        }
+                        _simpleValue = null;
+                        «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
+                        return _value;
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''
+                        return fromDomValue($1);
+                    '''
+                ]
+            ]
+
+            val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
+            val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+
+    }
+
+    private def dispatch String deserializeValue(Type type, String domParameter) '''(«type.resolvedName») «domParameter»'''
+
+    /** 
+     * Default catch all
+     * 
+     **/
+    private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, MethodSignature property) '''
+        «type.resolvedName» «property.name» = null;
+    '''
+
+    private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
+        MethodSignature property) {
+        _deserializeProperty(container, type.toInstance, property)
+    }
+
+    public static def toSetter(String it) {
+
+        if (startsWith("is")) {
+            return "set" + substring(2);
+        } else if (startsWith("get")) {
+            return "set" + substring(3);
+        }
+        return "set" + it;
+    }
+
+    /* 
+    private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        if(«property.name» != null) {
+            Object domValue = «type.serializer».toDomStatic(QNAME,«property.name»);
+            childNodes.add(domValue);
+        }
+    '''
+    */
+    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;
+        addField(field, '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
+    }
+
+    private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
+        {
+            «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.allProperties, node)»
+            return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+        }
+    '''
+
+    private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
+        {
+            «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.allProperties, node)»
+            return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+        }
+    '''
+
+    private def transformDataContainerBody(Map<String, MethodSignature> properties, DataNodeContainer node) {
+        val ret = '''
+            «FOR child : node.childNodes.filter[!augmenting]»
+                «val signature = properties.get(child.getterName)»
+                «serializeProperty(child, signature.returnType, signature)»
+            «ENDFOR»
+        '''
+        return ret;
+    }
+
+    private static def String getGetterName(DataSchemaNode node) {
+        return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
+    }
+
+    private static def String getGetterName(QName node) {
+        return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
+    }
+
+    private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
+        MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        if(«property.name» != null) {
+            java.util.Iterator _iterator = «property.name».iterator();
+            boolean _hasNext = _iterator.hasNext();
+            while(_hasNext) {
+                Object _listItem = _iterator.next();
+                Object _domValue = «type.actualTypeArguments.get(0).serializer.name».toDomStatic(QNAME,_listItem);
+                childNodes.add(_domValue);
+                _hasNext = _iterator.hasNext();
+            }
+        }
+    '''
+
+    private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        
+        if(«property.name» != null) {
+            «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»");
+            Object _propValue = «serializeValue(type, property.name)»;
+            if(_propValue != null) {
+                Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
+                childNodes.add(_domValue);
+            }
+        }
+    '''
+
+    private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.name».toDomValue(«parameter»)'''
+
+    private def dispatch serializeValue(Type signature, String property) '''«property»'''
+
+    private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, Type type, MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        if(«property.name» != null) {
+            «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»");
+            java.util.Iterator _iterator = «property.name».iterator();
+            boolean _hasNext = _iterator.hasNext();
+            while(_hasNext) {
+                Object _listItem = _iterator.next();
+                Object _propValue = «property.name»;
+                Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
+                childNodes.add(_domValue);
+                _hasNext = _iterator.hasNext();
+            }
+        }
+    '''
+
+    /** 
+     * Default catch all
+     * 
+     **/
+    private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        if(«property.name» != null) {
+            Object domValue = «property.name»;
+            childNodes.add(domValue);
+        }
+    '''
+
+    private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
+        MethodSignature property) {
+        serializeProperty(container, type.toInstance, property)
+    }
+
+    private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
+        MethodSignature property) '''
+        «property.returnType.resolvedName» «property.name» = value.«property.name»();
+        if(«property.name» != null) {
+            Object domValue = «type.serializer».toDomStatic(QNAME,«property.name»);
+            childNodes.add(domValue);
+        }
+    '''
+
+    private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
+        {
+            return ($r) java.util.Collections.singletonMap(this.QNAME,null);
+        }
+    '''
+
+    private def transformatorFqn(GeneratedType typeSpec) {
+        return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
+    }
+
+    private def transformatorFqn(Class typeSpec) {
+        return '''«typeSpec.name»$Broker$Codec$DOM'''
+    }
+
+    private def HashMap<String, MethodSignature> getAllProperties(GeneratedType type) {
+        val ret = new HashMap<String, MethodSignature>();
+        type.collectAllProperties(ret);
+        return ret;
+    }
+
+    private def dispatch void collectAllProperties(GeneratedType type, Map<String, MethodSignature> set) {
+        for (definition : type.methodDefinitions) {
+            set.put(definition.name, definition);
+        }
+
+        for (parent : type.implements) {
+            parent.collectAllProperties(set);
+        }
+    }
+
+    private def dispatch void collectAllProperties(Type type, Map<String, MethodSignature> set) {
+        // NOOP for generic type.
+    }
+
+    def String getResolvedName(Type type) {
+        return type.asCtClass.name;
+    }
+
+    def CtClass asCtClass(Type type) {
+        val name = type.fullyQualifiedName
+        val cls = loadClassWithTCCL(type.fullyQualifiedName)
+        return cls.asCtClass;
+    }
+
+}
+
+@Data
+class PropertyPair {
+
+    String getterName;
+
+    Type type;
+
+    @Property
+    MethodSignature signature;
+    @Property
+    SchemaNode schemaNode;
+}
index 0a8a7df..e2b7920 100644 (file)
@@ -47,10 +47,20 @@ import org.opendaylight.yangtools.yang.data.api.SimpleNode
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+import com.google.common.collect.HashMultimap
+import com.google.common.collect.ArrayListMultimap
+import com.google.common.collect.Multimap
+import java.util.Collection
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
 
 class BindingMapping {
 
+
+
+    @Property
     val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
+    
+    @Property
     val Map<Type, SchemaNode> typeToSchemaNode = new HashMap();
 
     def QName getSchemaNode(Class<?> cls) {
@@ -91,7 +101,7 @@ class BindingMapping {
 
     }
 
-    def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> parent) {
+    private def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> parent) {
         val Class rawType = argument.type;
         val ref = Types.typeForClass(rawType);
         val schemaType = typeToSchemaNode.get(ref);
@@ -103,13 +113,13 @@ class BindingMapping {
         return new NodeIdentifierWithPredicates(qname, predicates);
     }
     
-    def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
+    private def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
         val ref = Types.typeForClass(argument.type);
         val qname = typeToSchemaNode.get(ref).QName
         return new NodeIdentifier(qname);
     }
 
-    def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
+    private def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
         val keyDefinitions = node.keyDefinition;
         val map = new HashMap<QName, Object>();
         for (keydef : keyDefinitions) {
@@ -192,7 +202,7 @@ class BindingMapping {
         return Collections.emptyList();
     }
 
-    def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
+    private def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
         return Collections.emptyList();
     }
 
@@ -226,35 +236,35 @@ class BindingMapping {
         return it;
     }
 
-    private def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
+    public static def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
         getSimpleValue(container, name, type.baseType);
     }
 
-    private def dispatch Node<?> getSimpleValue(Object container, QName name, StringTypeDefinition type) {
+    public static def dispatch Node<?> getSimpleValue(Object container, QName name, StringTypeDefinition type) {
         val value = container.getValue(name, String);
         if(value === null) return null;
         return new SimpleNodeTOImpl(name, null, value);
     }
 
-    private def dispatch Node<?> getSimpleValue(Object container, QName name, TypeDefinition<?> type) {
+    public static def dispatch Node<?> getSimpleValue(Object container, QName name, TypeDefinition<?> type) {
         val value = container.getValue(name, Object);
         if(value === null) return null;
         return new SimpleNodeTOImpl(name, null, value);
     }
 
-    private def dispatch Node<?> getSimpleValue(Object container, QName name, BooleanTypeDefinition type) {
+    public static def dispatch Node<?> getSimpleValue(Object container, QName name, BooleanTypeDefinition type) {
         val value = container.getValue(name, Boolean);
         if(value === null) return null;
         return new SimpleNodeTOImpl(name, null, value);
     }
 
-    private def dispatch Node<?> getSimpleValue(Object container, QName name, BinaryTypeDefinition type) {
+    public static def dispatch Node<?> getSimpleValue(Object container, QName name, BinaryTypeDefinition type) {
         val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS);
         if(value === null) return null;
         return new SimpleNodeTOImpl(name, null, value);
     }
 
-    private def <T> T getValue(Object object, QName node, Class<T> type) {
+    public static def <T> T getValue(Object object, QName node, Class<T> type) {
         val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type));
         var clz = object.class;
         if (object instanceof DataContainer) {
@@ -274,7 +284,7 @@ class BindingMapping {
         return value.getEncapsulatedValue(type);
     }
 
-    private def <T> T getEncapsulatedValue(Object value, Class<T> type) {
+    public static def <T> T getEncapsulatedValue(Object value, Class<T> type) {
         val method = value.class.getMethod("getValue");
         if (method !== null && type.isAssignableFrom(method.returnType)) {
             return method.invoke(value) as T;
@@ -303,7 +313,7 @@ class BindingMapping {
         return buildMethod.invoke(builder) as DataObject;
     }
 
-    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+    private def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
         ListSchemaNode schema) {
 
         if (schema.keyDefinition !== null && !schema.keyDefinition.empty) {
@@ -311,14 +321,56 @@ class BindingMapping {
             val value = node.keyToBindingKey(loader, type, schema);
             builder.setProperty("key", value);
         }
+        node.fillBuilderFromContainer(builder,loader,type,schema);
     }
+    
+    
 
-    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+    private def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
         ContainerSchemaNode schema) {
+        node.fillBuilderFromContainer(builder,loader,type,schema);
     }
 
     
-    def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) {
+    private def void fillBuilderFromContainer(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, DataNodeContainer schema) {
+        val Multimap<QName,Node<?>> dataMap = ArrayListMultimap.create();
+        for(child :node.children) {
+            dataMap.put(child.nodeType,node);
+        }
+        for(entry : dataMap.asMap.entrySet) {
+            val entrySchema = schema.getDataChildByName(entry.key);
+            val entryType = type.methodDefinitions.byQName(entry.key);
+            entry.value.addValueToBuilder(builder,loader,entryType,entrySchema);
+        }
+    }
+    
+    private def Type byQName(List<MethodSignature> signatures, QName name) {
+      
+    }
+    
+    private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, LeafSchemaNode container) {
+        
+    }
+    
+    
+    
+    private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, ContainerSchemaNode container) {
+        
+    }
+    
+    
+    private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, ListSchemaNode container) {
+        
+    }
+    
+    private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, LeafListSchemaNode container) {
+        
+    }
+    
+    
+    
+    
+    private def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) {
         val keyClass = loader.loadClass(type.keyFQN);
         val constructor = keyClass.constructors.get(0);
         val keyType = type.keyTypeProperties;
@@ -336,22 +388,22 @@ class BindingMapping {
         return ClassLoaderUtils.construct(constructor, args);
     }
 
-    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+    private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
         LeafSchemaNode node2) {
         deserializeSimpleValueImpl(node, loader, type, node2.type);
     }
 
-    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+    private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
         LeafListSchemaNode node2) {
         deserializeSimpleValueImpl(node, loader, type, node2.type);
     }
 
-    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
         ExtendedType definition) {
         deserializeSimpleValueImpl(node, loader, type, definition.baseType);
     }
 
-    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
         StringTypeDefinition definition) {
         if (type instanceof GeneratedTransferObject) {
             val cls = loader.getClassForType(type);
@@ -362,16 +414,16 @@ class BindingMapping {
         return node.value;
     }
 
-    def Class<?> getClassForType(ClassLoader loader, Type type) {
+    private def Class<?> getClassForType(ClassLoader loader, Type type) {
         loader.loadClass(type.fullyQualifiedName);
     }
 
-    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
         TypeDefinition definition) {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
     }
 
-    def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
+    private def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
         val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"]
         val key = method.returnType as GeneratedTransferObject;
         val ret = new HashMap<String, GeneratedProperty>();
@@ -381,16 +433,16 @@ class BindingMapping {
         return ret;
     }
 
-    def void setProperty(Object object, String property, Object value) {
+    private def void setProperty(Object object, String property, Object value) {
         val cls = object.class;
         val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class);
         if (valMethod != null)
             valMethod.invoke(object, value);
     }
 
-    def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
+    private def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
 
-    def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
+    private def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
 
 }
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CompositeNodeUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CompositeNodeUtils.java
new file mode 100644 (file)
index 0000000..5d17d92
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class CompositeNodeUtils {
+
+}
index c96835b..af18e9c 100644 (file)
@@ -3,7 +3,10 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom;
 import java.util.Collection;
 import java.util.Collections;
 
+import javassist.ClassPool;
+
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
@@ -38,10 +41,12 @@ public class ConnectorActivator implements Provider, ServiceTrackerCustomizer<Br
     @Override
     public void onSessionInitiated(ProviderSession session) {
 
-        MappingServiceImpl mappingImpl = new MappingServiceImpl();
-        mappingImpl.setSchemaService(session.getService(SchemaService.class));
+        RuntimeGeneratedMappingServiceImpl mappingImpl = new RuntimeGeneratedMappingServiceImpl();
+        SchemaService schemaService = (session.getService(SchemaService.class));
+        ClassPool pool = new ClassPool();
+        mappingImpl.setBinding(new TransformerGenerator(pool));
         mappingImpl.start();
-
+        schemaService.registerSchemaServiceListener(mappingImpl);
         mappingService = mappingImpl;
         dataConnector = new BindingIndependentDataServiceConnector();
         dataConnector.setBaDataService(baDataService);
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RuntimeGeneratedMappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RuntimeGeneratedMappingServiceImpl.xtend
new file mode 100644 (file)
index 0000000..c1efd11
--- /dev/null
@@ -0,0 +1,235 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator
+import javassist.ClassPool
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import java.util.Map
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import java.util.HashMap
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import java.util.Map.Entry
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import static com.google.common.base.Preconditions.*;
+import java.util.List
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.concepts.Delegator
+import java.util.concurrent.ConcurrentMap
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.yang.binding.BindingCodec
+
+class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener {
+
+    ClassPool pool;
+
+    @Property
+    extension TransformerGenerator binding;
+    
+    val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
+
+    val ConcurrentMap<Class<? extends DataContainer>, TransformerWrapper> domSerializers = new ConcurrentHashMap();
+
+    @Property
+    val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+
+    @Property
+    val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
+
+    override onGlobalContextUpdated(SchemaContext arg0) {
+        recreateBindingContext(arg0);
+    }
+
+    def recreateBindingContext(SchemaContext schemaContext) {
+        val newBinding = new BindingGeneratorImpl();
+        newBinding.generateTypes(schemaContext);
+
+        for (entry : newBinding.moduleContexts.entrySet) {
+
+            //val module = entry.key;
+            val context = entry.value;
+            updateBindingFor(context.childNodes, schemaContext);
+            
+            val typedefs = context.typedefs;
+            for(typedef : typedefs.values) {
+                binding.typeDefinitions.put(typedef,typedef as GeneratedType);
+            }
+        }
+    }
+
+    override CompositeNode toDataDom(DataObject data) {
+        toCompositeNodeImpl(data);
+    }
+
+    override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+        Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+        val key = toDataDomImpl(entry.key);
+        val data = toCompositeNodeImpl(entry.value);
+        return new SimpleEntry(key, data);
+    }
+
+    private def CompositeNode toCompositeNodeImpl(DataObject object) {
+        val cls = object.implementedInterface;
+        val transformator = resolveTransformator(cls);
+        val ret = transformator.transform(object);
+        return ret;
+    }
+
+    private def resolveTransformator(Class<? extends DataContainer> cls) {
+        val serializer = domSerializers.get(cls);
+        if (serializer !== null) {
+            return serializer;
+        }
+        val transformerClass = binding.transformerFor(cls).newInstance;
+        val wrapper = new TransformerWrapper(transformerClass);
+        domSerializers.putIfAbsent(cls, wrapper);
+        return wrapper;
+    }
+
+    private def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDomImpl(
+        InstanceIdentifier<? extends DataObject> object) {
+        val pathArguments = object.path;
+        var Class<? extends DataObject> parent;
+        val dataDomArgs = new ArrayList<PathArgument>();
+        for (pathArgument : pathArguments) {
+            dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
+            parent = pathArgument.type;
+        }
+
+        return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
+    }
+
+    override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> path) {
+        return toDataDomImpl(path);
+    }
+
+    override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
+        return dataObjectFromDataDomImpl(path, result);
+    }
+
+    def DataObject dataObjectFromDataDomImpl(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
+        val targetType = identifier.targetType
+        val transformer = resolveTransformator(targetType);
+        val ret = transformer.deserialize(node) as DataObject;
+        return ret;
+    }
+
+    def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+        for (entry : map.entrySet) {
+            val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+            typeToDefinition.put(entry.value, entry.value);
+            typeToSchemaNode.put(entry.value, schemaNode)
+        }
+    }
+
+    private def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument,
+        Class<? extends DataObject> parent) {
+        val Class<?> rawType = argument.type;
+        val ref = Types.typeForClass(rawType);
+        val schemaType = typeToSchemaNode.get(ref);
+        val qname = schemaType.QName
+
+        val Object key = argument.key;
+        val predicates = key.toPredicates(schemaType as ListSchemaNode);
+
+        return new NodeIdentifierWithPredicates(qname, predicates);
+    }
+
+    private def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
+        val keyDefinitions = node.keyDefinition;
+        val map = new HashMap<QName, Object>();
+        for (keydef : keyDefinitions) {
+            val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
+            val value = BindingMapping.getSimpleValue(identifier, keydef, keyNode.type);
+            map.put(keydef, value.value);
+        }
+        return map;
+    }
+
+    private def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
+        val ref = Types.typeForClass(argument.type);
+        val qname = typeToSchemaNode.get(ref).QName
+        return new NodeIdentifier(qname);
+    }
+
+    public def void start() {
+        pool = new ClassPool()
+        binding = new TransformerGenerator(pool);
+
+        binding.typeToDefinition = typeToDefinition
+        binding.typeToSchemaNode = typeToSchemaNode
+        binding.typeDefinitions = typeDefinitions
+
+    }
+}
+
+class TransformerWrapper implements // //
+Delegator<BindingCodec<Map<QName, Object>, Object>> {
+
+    @Property
+    val BindingCodec<Map<QName, Object>, Object> delegate;
+
+    new(BindingCodec<Map<QName, Object>, Object> delegate) {
+        _delegate = delegate;
+    }
+
+    def CompositeNode transform(DataObject input) {
+        val ret = delegate.serialize(input);
+        val node = toNode(ret)
+        return node as CompositeNode;
+    }
+
+    def deserialize(CompositeNode node) {
+        if (node === null) {
+            return null;
+        }
+        val Map mapCapture = node
+        return delegate.deserialize(mapCapture as Map<QName,Object>);
+    }
+
+    static def Node<?> toNode(Map map) {
+        val nodeMap = map as Map<QName,Object>;
+        checkArgument(map.size == 1);
+        val elem = nodeMap.entrySet.iterator.next;
+        val qname = elem.key;
+        val value = elem.value;
+        toNodeImpl(qname, value);
+    }
+
+    static def dispatch Node<?> toNodeImpl(QName name, List objects) {
+        val values = new ArrayList<Node<?>>(objects.size);
+        for (obj : objects) {
+            values.add(toNode(obj as Map));
+        }
+        return new CompositeNodeTOImpl(name, null, values);
+    }
+
+    static def dispatch Node<?> toNodeImpl(QName name, Map<QName, Object> object) {
+        throw new UnsupportedOperationException("Unsupported node hierarchy.");
+    }
+
+    static def dispatch Node<?> toNodeImpl(QName name, Object object) {
+        return new SimpleNodeTOImpl(name, null, object);
+    }
+}
index ccf99df..0b91658 100644 (file)
@@ -10,8 +10,6 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 
-import org.opendaylight.yangtools.yang.binding.Identifier;
-
 public class ClassLoaderUtils {
     
     public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
@@ -33,4 +31,9 @@ public class ClassLoaderUtils {
     Object[] initargs = objects.toArray(new Object[]{});
     return constructor.newInstance(initargs);
     }
+    
+    
+    public static Class<?> loadClassWithTCCL(String name) throws ClassNotFoundException {
+        return Thread.currentThread().getContextClassLoader().loadClass(name);
+    }
 }
\ No newline at end of file
index 0448238..0e35ee6 100644 (file)
@@ -14,7 +14,9 @@ import org.opendaylight.controller.sal.binding.api.data.DataModificationTransact
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -34,8 +36,8 @@ public class BrokerIntegrationTest {
 
     DataBrokerService biDataService;
     DataProviderService baDataService;
-    private MappingServiceImpl mappingServiceImpl;
-    private MappingServiceImpl mappingService;
+    private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+    private BindingIndependentMappingService mappingService;
     private DataBrokerImpl baDataImpl;
     private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
     private ListeningExecutorService executor;
@@ -60,9 +62,9 @@ public class BrokerIntegrationTest {
         biDataImpl.registerOperationalReader(treeRoot, dataStore);
         biDataImpl.registerCommitHandler(treeRoot, dataStore);
         
-        mappingServiceImpl = new MappingServiceImpl();
+        mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
         mappingService = mappingServiceImpl;
-        
+        mappingServiceImpl.start();
         
         connectorServiceImpl = new BindingIndependentDataServiceConnector();
         connectorServiceImpl.setBaDataService(baDataService);
@@ -73,20 +75,21 @@ public class BrokerIntegrationTest {
         String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
         "node-inventory.yang" };
         
-        mappingService.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
+        mappingServiceImpl.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
+        
     }
     
     @Test
     public void simpleModifyOperation() throws Exception {
         
-        DataModificationTransaction transaction = baDataService.beginTransaction();
-        assertNotNull(transaction);
         
         NodeRef node1 = createNodeRef("0");
         DataObject  node = baDataService.readConfigurationData(node1.getValue());
         assertNull(node);
         Node nodeData1 = createNode("0");
         
+        
+        DataModificationTransaction transaction = baDataService.beginTransaction();
         transaction.putConfigurationData(node1.getValue(), nodeData1);
         Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
         assertNotNull(commitResult);
@@ -102,18 +105,50 @@ public class BrokerIntegrationTest {
         assertEquals(nodeData1.getKey(), readedData.getKey());
         
         
-        DataModificationTransaction transaction2 = baDataService.beginTransaction();
+        NodeRef nodeFoo = createNodeRef("foo");
+        NodeRef nodeBar = createNodeRef("bar");
+        Node nodeFooData = createNode("foo");
+        Node nodeBarData = createNode("bar");
+        
+        
+        DataModificationTransaction insertMoreTr = baDataService.beginTransaction();
+        insertMoreTr.putConfigurationData(nodeFoo.getValue(), nodeFooData);
+        insertMoreTr.putConfigurationData(nodeBar.getValue(), nodeBarData);
+        RpcResult<TransactionStatus> result2 = insertMoreTr.commit().get();
+        
+        assertNotNull(result2);
+        assertNotNull(result2.getResult());
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        
+        Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder().node(Nodes.class).toInstance());
+        assertNotNull(allNodes);
+        assertNotNull(allNodes.getNode());
+        assertEquals(3, allNodes.getNode().size());
+        
+        
+        /**
+         * We create transaction no 2
+         * 
+         */
+        DataModificationTransaction removalTransaction = baDataService.beginTransaction();
         assertNotNull(transaction);
         
-        transaction2.removeConfigurationData(node1.getValue());
+        /**
+         * We remove node 1
+         * 
+         */
+        removalTransaction.removeConfigurationData(node1.getValue());
         
-        Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
+        /**
+         * We commit transaction
+         */
+        Future<RpcResult<TransactionStatus>> commitResult2 = removalTransaction.commit();
         assertNotNull(commitResult2);
         
-        RpcResult<TransactionStatus> result2 = commitResult2.get();
+        RpcResult<TransactionStatus> result3 = commitResult2.get();
         
-        assertNotNull(result2);
-        assertNotNull(result2.getResult());
+        assertNotNull(result3);
+        assertNotNull(result3.getResult());
         assertEquals(TransactionStatus.COMMITED, result2.getResult());
     
         DataObject readedData2 = baDataService.readConfigurationData(node1.getValue());