Merge "Ganymed ChannelManager hack for subsystem command"
authorEd Warnicke <eaw@cisco.com>
Tue, 19 Nov 2013 20:07:20 +0000 (20:07 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 19 Nov 2013 20:07:20 +0000 (20:07 +0000)
72 files changed:
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/action-types.yang
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/XtendHelper.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/util/JavassistUtils.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCaseCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DataContainerCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DomCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/IdentifierCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/InstanceIdentifierCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ValueWithQName.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/BindingClassListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/GeneratorListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/IntermediateMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/StaticFieldInitializer.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
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend [deleted file]
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/MappingServiceImpl.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RuntimeGeneratedMappingServiceImpl.xtend [deleted file]
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/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 [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java [deleted file]
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 [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromJsonToCompositeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicDataTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data1.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/multiple-items-in-list.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container-yang/simple-container.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list-yang/simple-list.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level1.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level2.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level3.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container-yang/data-container.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-container.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-list.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/empty-data.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/simple-data-types.yang
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/xml/data.xml

index 0b84d905dfff907b82b88d287d5d70c94bdc43a0..18a22bb26fa91560dcc24be28a5e9c65877413c1 100644 (file)
@@ -51,6 +51,8 @@ public abstract class AbstractConfigTest extends
     protected ConfigRegistryJMXClient configRegistryClient;
     protected BaseJMXRegistrator baseJmxRegistrator;
     protected InternalJMXRegistrator internalJmxRegistrator;
+    protected BundleContext mockedContext;
+    protected ServiceRegistration<?> mockedServiceRegistration;
 
     // this method should be called in @Before
     protected void initConfigTransactionManagerImpl(
@@ -60,16 +62,16 @@ public abstract class AbstractConfigTest extends
 
         configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
                 platformMBeanServer);
-        BundleContext context = mock(BundleContext.class);
-        ServiceRegistration<?> mockedServiceRegistration = mock(ServiceRegistration.class);
+        this.mockedContext = mock(BundleContext.class);
+        this.mockedServiceRegistration = mock(ServiceRegistration.class);
         doNothing().when(mockedServiceRegistration).unregister();
-        doReturn(mockedServiceRegistration).when(context).registerService(
+        doReturn(mockedServiceRegistration).when(mockedContext).registerService(
                 Matchers.any(String[].class), any(Closeable.class),
                 any(Dictionary.class));
         internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
         baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
 
-        configRegistry = new ConfigRegistryImpl(resolver, context,
+        configRegistry = new ConfigRegistryImpl(resolver, mockedContext,
                 platformMBeanServer, baseJmxRegistrator);
         try {
             configRegistryJMXRegistrator.registerToJMX(configRegistry);
index 5bfe54e4c32a7132a0fe8e8e9c53908e0e4f6aa0..3850dd551fd42abd8725a7262952235efd13c980 100644 (file)
@@ -5,7 +5,7 @@ module opendaylight-action-types {
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
     import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
-    import opendaylight-match-types {prefix match; revision-date 2013-10-26";}
+    import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
     
     revision "2013-11-12" {
         description "Initial revision of action service";
index fbd87d17beede977e4efa2b987f077352522481c..f0f92da18e5c3b2235eb77a9cf3d0e32b8df371c 100644 (file)
@@ -39,7 +39,7 @@ class RuntimeCodeHelper {
     public static def void setDelegate(RpcService proxy, RpcService delegate) {
         val field = proxy.class.getField(DELEGATE_FIELD)
         if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy");
-        if (field.type.isAssignableFrom(delegate.class)) {
+        if (delegate == null || field.type.isAssignableFrom(delegate.class)) {
             field.set(proxy, delegate)
         } else
             throw new IllegalArgumentException("delegate class is not assignable to proxy");
@@ -55,7 +55,7 @@ class RuntimeCodeHelper {
     public static def void setDelegate(Object proxy, Object delegate) {
         val field = proxy.class.getField(DELEGATE_FIELD)
         if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy");
-        if (field.type.isAssignableFrom(delegate.class)) {
+        if (delegate == null || field.type.isAssignableFrom(delegate.class)) {
             field.set(proxy, delegate)
         } else
             throw new IllegalArgumentException("delegate class is not assignable to proxy");
index 5b11ec72077876dbe6f2f95183977e30273b7d10..b6dcde19ee18a4ae3e05571b6c56e448d50c1794 100644 (file)
@@ -8,7 +8,6 @@ import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeC
 import java.util.Set
 import java.util.HashMap
 import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable
-import static org.opendaylight.controller.sal.binding.codegen.impl.XtendHelper.*
 import org.opendaylight.yangtools.yang.binding.DataContainer
 import org.opendaylight.yangtools.yang.binding.RpcImplementation
 
index 21b48bb47511699dfef265ed46c6c90dc2be52c6..83096514465a4814c86ad751493dec1d6e1fc156 100644 (file)
@@ -9,8 +9,4 @@ public class XtendHelper {
             Class<C> cls) {
         return new RpcRoutingTableImpl<>(cls);
     }
-    
-    public static String foo() {
-        return "Foo";
-    }
 }
index 19737b83c628caa531edb74d3fbb8bcc1531d2db..802e7acb5bb993976a8a5d04a1c1776a6c8a67c8 100644 (file)
@@ -10,10 +10,15 @@ import javassist.Modifier
 import javassist.NotFoundException
 import javassist.LoaderClassPath
 import javassist.ClassClassPath
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
 
 class JavassistUtils {
 
     ClassPool classPool
+    
+    @Property
+    val Lock lock = new ReentrantLock();
 
     new(ClassPool pool) {
         classPool = pool;
@@ -49,12 +54,14 @@ class JavassistUtils {
     }
 
     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);
@@ -76,6 +83,13 @@ class JavassistUtils {
         addField(field);
         return field;
     }
+    
+    def CtField staticField(CtClass it, String name, Class<?> returnValue) {
+        val field = new CtField(returnValue.asCtClass, name, it);
+        field.modifiers = Modifier.PUBLIC + Modifier.STATIC
+        addField(field);
+        return field;
+    }
 
     def get(ClassPool pool, Class<?> cls) {
         try {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java
new file mode 100644 (file)
index 0000000..cdddec7
--- /dev/null
@@ -0,0 +1,15 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface AugmentationCodec<A extends Augmentation<?>> extends DomCodec<A> {
+
+    
+    @Override
+    public CompositeNode serialize(ValueWithQName<A> input);
+    
+    @Override
+    public ValueWithQName<A> deserialize(Node<?> input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCaseCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCaseCodec.java
new file mode 100644 (file)
index 0000000..d545b72
--- /dev/null
@@ -0,0 +1,16 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface ChoiceCaseCodec<C extends DataContainer> extends DataContainerCodec<C> {
+
+    @Override
+    public CompositeNode serialize(ValueWithQName<C> input);
+    
+    @Override
+    public ValueWithQName<C> deserialize(Node<?> input);
+    
+    public boolean isAcceptable(Node<?> input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ChoiceCodec.java
new file mode 100644 (file)
index 0000000..21bb1cf
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface ChoiceCodec<C> extends DomCodec<C> {
+
+    @Override
+    public Node<?> serialize(ValueWithQName<C> input);
+    
+    @Override
+    public ValueWithQName<C> deserialize(Node<?> input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java
new file mode 100644 (file)
index 0000000..1a02ea1
--- /dev/null
@@ -0,0 +1,32 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
+
+
+public interface CodecRegistry {
+
+    InstanceIdentifierCodec getInstanceIdentifierCodec();
+
+    <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> object);
+
+    <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> object);
+
+    <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object);
+
+    <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object);
+
+    Class<?> getClassForPath(List<QName> names);
+
+    IdentifierCodec<?> getKeyCodecForPath(List<QName> names);
+    
+    
+    void bindingClassEncountered(Class<?> cls);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DataContainerCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DataContainerCodec.java
new file mode 100644 (file)
index 0000000..683faaf
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface DataContainerCodec<T extends DataContainer> extends  DomCodec<T> {
+
+
+    @Override
+    public ValueWithQName<T> deserialize(Node<?> input);
+    
+    @Override
+    public CompositeNode serialize(ValueWithQName<T> input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DomCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/DomCodec.java
new file mode 100644 (file)
index 0000000..76969ab
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface DomCodec<I> extends BindingCodec<Node<?>, ValueWithQName<I>>{
+    
+    
+    @Override
+    public Node<?> serialize(ValueWithQName<I> input);
+    
+    
+    @Override
+    public ValueWithQName<I> deserialize(Node<?> input);
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/IdentifierCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/IdentifierCodec.java
new file mode 100644 (file)
index 0000000..933b884
--- /dev/null
@@ -0,0 +1,14 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface IdentifierCodec<I extends Identifier<?>> extends DomCodec<I> {
+
+    @Override
+    public ValueWithQName<I> deserialize(Node<?> input);
+    
+    @Override
+    public CompositeNode serialize(ValueWithQName<I> input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/InstanceIdentifierCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/InstanceIdentifierCodec.java
new file mode 100644 (file)
index 0000000..7fbb79d
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface InstanceIdentifierCodec extends BindingCodec<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier,InstanceIdentifier<?>> {
+
+    @Override
+    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(InstanceIdentifier<?> input);
+    
+    @Override
+    public InstanceIdentifier<?> deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ValueWithQName.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/ValueWithQName.java
new file mode 100644 (file)
index 0000000..442df01
--- /dev/null
@@ -0,0 +1,72 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class ValueWithQName<V> implements Entry<QName, V>{
+    
+    final QName qname;
+    final V value;
+    
+    public ValueWithQName(QName qname, V value) {
+        super();
+        this.qname = qname;
+        this.value = value;
+    }
+
+    public QName getQname() {
+        return qname;
+    }
+
+    public V getValue() {
+        return value;
+    }
+    
+    @Override
+    public QName getKey() {
+        return qname;
+    }
+    
+    @Override
+    public V setValue(V value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+        result = prime * result + ((value == null) ? 0 : value.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        @SuppressWarnings("rawtypes")
+        ValueWithQName other = (ValueWithQName) obj;
+        if (qname == null) {
+            if (other.qname != null)
+                return false;
+        } else if (!qname.equals(other.qname))
+            return false;
+        if (value == null) {
+            if (other.value != null) {
+                return false;
+            }
+        } else if (!value.equals(other.value)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/BindingClassListener.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/BindingClassListener.java
new file mode 100644 (file)
index 0000000..c2b5635
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+public interface BindingClassListener {
+
+    void onBindingClassCaptured(Class<?> cls);
+    
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java
new file mode 100644 (file)
index 0000000..19e9961
--- /dev/null
@@ -0,0 +1,79 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec;
+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 {
+
+    public static final String INSTANCE_IDENTIFIER_CODEC = "INSTANCE_IDENTIFIER_CODEC";
+    public static final String CLASS_TO_CASE_MAP = "CLASS_TO_CASE";
+    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) {
+        Field instanceIdField;
+        try {
+            instanceIdField = obj.getField(INSTANCE_IDENTIFIER_CODEC);
+            instanceIdField.set(null, codec);
+        } catch (NoSuchFieldException e) {
+           // NOOP
+        } catch (SecurityException e) {
+            // NOOP
+        } catch (IllegalAccessException e) {
+            // NOOp
+        }
+    }
+
+    public static void setClassToCaseMap(Class<? extends BindingCodec> codec,
+            Map<Class,BindingCodec> classToCaseRawCodec) {
+        Field instanceIdField;
+        try {
+            instanceIdField = codec.getField(CLASS_TO_CASE_MAP);
+            instanceIdField.set(null, classToCaseRawCodec);
+        } catch (NoSuchFieldException e) {
+           // NOOP
+        } catch (SecurityException e) {
+            // NOOP
+        } catch (IllegalAccessException e) {
+            // NOOp
+        }
+        
+        
+    }
+
+    public static void setCompositeNodeToCaseMap(Class<? extends BindingCodec> codec,
+            Map<CompositeNode,BindingCodec> compositeToCase) {
+        Field instanceIdField;
+        try {
+            instanceIdField = codec.getField(COMPOSITE_TO_CASE);
+            instanceIdField.set(null, compositeToCase);
+        } catch (NoSuchFieldException e) {
+           // NOOP
+        } catch (SecurityException e) {
+            // NOOP
+        } catch (IllegalAccessException e) {
+            // NOOp
+        }
+    }
+
+    public static void setAugmentationCodec(Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec,
+            BindingCodec augmentableCodec) {
+            Field instanceIdField;
+            try {
+                instanceIdField = dataCodec.getField(AUGMENTATION_CODEC);
+                instanceIdField.set(null, augmentableCodec);
+            } catch (NoSuchFieldException e) {
+               // NOOP
+            } catch (SecurityException e) {
+                // NOOP
+            } catch (IllegalAccessException e) {
+                // NOOp
+            }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java
new file mode 100644 (file)
index 0000000..048dc3a
--- /dev/null
@@ -0,0 +1,17 @@
+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 {
+
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public static IdentifiableItem<?, ?> newIdentifiableItem(Class<?> type, Object key) {
+        Class<? extends Identifiable<?>> identifiableType = (Class<? extends Identifiable<?>>) type;
+        Identifier<? extends Identifiable<?>> identifier = (Identifier<? extends Identifiable<?>>) key;
+        return new IdentifiableItem(identifiableType,identifier);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/GeneratorListener.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/GeneratorListener.java
new file mode 100644 (file)
index 0000000..3f74c9e
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface GeneratorListener {
+
+    
+    
+    void onCodecCreated(Class<?> codec);
+    void onValueCodecCreated(Class<?> valueClass,Class<?> valueCodec);
+    void onChoiceCodecCreated(Class<?> choiceClass,Class<? extends BindingCodec<Map<QName, Object>,Object>> choiceCodec);
+    void onCaseCodecCreated(Class<?> choiceClass,Class<? extends BindingCodec<Map<QName, Object>,Object>> choiceCodec);
+    public abstract void onDataContainerCodecCreated(Class<?> dataClass, Class<?  extends BindingCodec<Map<QName, Object>,Object>> dataCodec);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend
new file mode 100644 (file)
index 0000000..fd02fde
--- /dev/null
@@ -0,0 +1,123 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import java.util.Map
+import java.util.WeakHashMap
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
+import java.util.HashMap
+import org.slf4j.LoggerFactory
+import java.util.List
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+
+class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
+    
+    private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
+    val CodecRegistry codecRegistry;
+    
+    val Map<Class<?>,QName> classToQName = new WeakHashMap;
+    
+    
+    public new(CodecRegistry registry) {
+        codecRegistry = registry;
+    }
+    
+    
+    override deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
+        var Class<?> baType = null
+        val biArgs = input.path
+        val scannedPath = new ArrayList<QName>(biArgs.size);
+        val baArgs = new ArrayList<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
+        for(biArg : biArgs) {
+            scannedPath.add(biArg.nodeType);
+            val baArg = deserializePathArgument(biArg,scannedPath)
+            baArgs.add(baArg)
+            baType = baArg?.type
+        }
+        val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
+        return ret;
+    }
+    
+    private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
+        val Class cls = codecRegistry.getClassForPath(processedPath);
+        return new Item(cls);
+    }
+    
+    
+    private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
+        val Class type = codecRegistry.getClassForPath(processedPath);
+        val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
+        val value = codec.deserialize(argument.toCompositeNode())?.value;
+        return CodecTypeUtils.newIdentifiableItem(type,value);
+    }
+    
+    def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
+        val keyValues = predicates.keyValues.entrySet;
+        val values = new ArrayList<Node<?>>(keyValues.size)
+        for(keyValue : keyValues) {
+            values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
+        }
+        return new CompositeNodeTOImpl(predicates.nodeType,null,values);
+    }
+    
+    override serialize(InstanceIdentifier input) {
+        val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
+        var QName previousQName = null;
+        val components = new ArrayList<PathArgument>(pathArgs.size);
+        for(baArg : pathArgs) { 
+            codecRegistry.bindingClassEncountered(baArg.type);
+            val biArg = serializePathArgument(baArg,previousQName);
+            previousQName = biArg.nodeType;
+            components.add(biArg);
+        }
+        return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
+    }
+    
+    private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
+        val type = argument.type;
+        val qname = resolveQname(type);
+        if(previousQname == null) {
+            return new NodeIdentifier(qname);
+        }
+        return new NodeIdentifier(QName.create(previousQname,qname.localName));
+    }
+    
+    private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
+        val Map<QName,Object> predicates = new HashMap();
+        val type = argument.type;
+        val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
+        val qname = resolveQname(type);
+        val combinedInput =  new ValueWithQName(previousQname,argument.key)
+        val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
+        for(outputValue :compositeOutput.value) {
+            predicates.put(outputValue.nodeType,outputValue.value);
+        }
+        if(previousQname == null) {
+            return new NodeIdentifierWithPredicates(qname,predicates);
+        }
+        return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
+    }
+    
+    def resolveQname(Class class1) {
+        val qname = classToQName.get(class1);
+        if(qname !== null) {
+            return qname;
+        }
+        val qnameField = class1.getField("QNAME");
+        val qnameValue = qnameField.get(null) as QName;
+        classToQName.put(class1,qnameValue);
+    }
+}
\ 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/IntermediateMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/IntermediateMapping.xtend
new file mode 100644 (file)
index 0000000..d0b114e
--- /dev/null
@@ -0,0 +1,40 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import org.opendaylight.yangtools.yang.data.api.Node
+import java.util.Map
+import org.opendaylight.yangtools.yang.common.QName
+import java.util.List
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import com.google.common.base.Preconditions
+
+class IntermediateMapping {
+    
+    
+    
+    static def Node<?> toNode(Map map) {
+        val nodeMap = map as Map<QName,Object>;
+        Preconditions.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);
+    } 
+}
\ 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/LazyGeneratedCodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
new file mode 100644 (file)
index 0000000..e8e4c43
--- /dev/null
@@ -0,0 +1,779 @@
+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;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.opendaylight.controller.sal.binding.dom.serializer.api.AugmentationCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCaseCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.DomCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.*;
+import static org.opendaylight.controller.sal.binding.dom.serializer.impl.IntermediateMapping.*;
+
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+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.Module;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+
+public class LazyGeneratedCodecRegistry implements //
+        CodecRegistry, //
+        SchemaServiceListener, //
+        GeneratorListener {
+
+    private final static Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
+    private final static LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
+
+    private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
+
+    private TransformerGenerator generator;
+
+    // Concrete class to codecs
+    private Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
+    private Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
+    private Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
+    private Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
+    private Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
+
+    /** Binding type to encountered classes mapping **/
+    @SuppressWarnings("rawtypes")
+    Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
+
+    @SuppressWarnings("rawtypes")
+    private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
+
+    private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
+
+    Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
+
+    private SchemaContext currentSchema;
+
+    public TransformerGenerator getGenerator() {
+        return generator;
+    }
+
+    public void setGenerator(TransformerGenerator generator) {
+        this.generator = generator;
+    }
+
+    @Override
+    public InstanceIdentifierCodec getInstanceIdentifierCodec() {
+        return instanceIdentifierCodec;
+    }
+
+    @Override
+    public <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Class<?> getClassForPath(List<QName> names) {
+        DataSchemaNode node = getSchemaNode(names);
+        SchemaPath path = node.getPath();
+        GeneratedTypeBuilder type = pathToType.get(path);
+        ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+        @SuppressWarnings("rawtypes")
+        WeakReference<Class> weakRef = typeToClass.get(typeref);
+        return weakRef.get();
+    }
+
+    @Override
+    public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
+        @SuppressWarnings("unchecked")
+        Class<? extends Identifiable<?>> cls = (Class<? extends Identifiable<?>>) getClassForPath(names);
+        return getIdentifierCodecForIdentifiable(cls);
+    }
+
+    @Override
+    public <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> type) {
+        @SuppressWarnings("unchecked")
+        DataContainerCodec<T> ret = (DataContainerCodec<T>) containerCodecs.get(type);
+        if (ret != null) {
+            return ret;
+        }
+        Class<? extends BindingCodec<Map<QName, Object>, Object>> newType = generator.transformerFor(type);
+        BindingCodec<Map<QName, Object>, Object> rawCodec = newInstanceOf(newType);
+        DataContainerCodecImpl<T> newWrapper = new DataContainerCodecImpl<>(rawCodec);
+        containerCodecs.put(type, newWrapper);
+        return newWrapper;
+    }
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    public void bindingClassEncountered(Class cls) {
+        ConcreteType typeRef = Types.typeForClass(cls);
+        WeakReference<Class> weakRef = new WeakReference<>(cls);
+        typeToClass.put(typeRef, weakRef);
+    }
+
+    private DataSchemaNode getSchemaNode(List<QName> path) {
+        QName firstNode = path.get(0);
+        DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
+                firstNode.getRevision());
+        Iterator<QName> iterator = path.iterator();
+        while (iterator.hasNext()) {
+            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) {
+                checkState(!iterator.hasNext(), "Path tries to nest inside leaf node.");
+                return currentNode;
+            }
+        }
+        return (DataSchemaNode) previous;
+    }
+
+    private 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 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 <T> T newInstanceOf(Class<?> newType) {
+        try {
+            @SuppressWarnings("unchecked")
+            T ret = (T) newType.newInstance();
+            return ret;
+        } catch (InstantiationException e) {
+            throw new IllegalStateException(e);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> type) {
+        IdentifierCodec<?> obj = identifierCodecs.get(type);
+        if (obj != null) {
+            return obj;
+        }
+        Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
+                .keyTransformerForIdentifiable(type);
+        BindingCodec<Map<QName, Object>, Object> newInstance;
+        newInstance = newInstanceOf(newCodec);
+        IdentifierCodecImpl<?> newWrapper = new IdentifierCodecImpl<>(newInstance);
+        identifierCodecs.put(type, newWrapper);
+        return newWrapper;
+    }
+
+    @Override
+    public void onCodecCreated(Class<?> cls) {
+        CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec);
+    }
+
+    @Override
+    public <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object) {
+        @SuppressWarnings("unchecked")
+        IdentifierCodec<T> obj = (IdentifierCodec<T>) identifierCodecs.get(object);
+        if (obj != null) {
+            return obj;
+        }
+        Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
+                .keyTransformerForIdentifier(object);
+        BindingCodec<Map<QName, Object>, Object> newInstance;
+        newInstance = newInstanceOf(newCodec);
+        IdentifierCodecImpl<T> newWrapper = new IdentifierCodecImpl<>(newInstance);
+        identifierCodecs.put(object, newWrapper);
+        return newWrapper;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public ChoiceCaseCodecImpl getCaseCodecFor(Class caseClass) {
+        ChoiceCaseCodecImpl<?> potential = caseCodecs.get(caseClass);
+        if (potential != null) {
+            return potential;
+        }
+        ConcreteType typeref = Types.typeForClass(caseClass);
+        ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
+
+        @SuppressWarnings("unchecked")
+        Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
+        BindingCodec newInstance = newInstanceOf(newCodec);
+        caseCodec.setDelegate(newInstance);
+        caseCodecs.put(caseClass, caseCodec);
+
+        for (Entry<Class<?>, ChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
+            if (choice.getKey().isAssignableFrom(caseClass)) {
+                choice.getValue().cases.put(caseClass, caseCodec);
+            }
+        }
+        return caseCodec;
+    }
+
+    public void onModuleContextAdded(SchemaContext schemaContext, Module module, ModuleContext context) {
+        pathToType.putAll(context.getChildNodes());
+
+        captureCases(context.getCases(), schemaContext);
+    }
+
+    private void captureCases(Map<SchemaPath, GeneratedTypeBuilder> cases, SchemaContext module) {
+        for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
+            ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
+                    .getValue().getName());
+            ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+            @SuppressWarnings("rawtypes")
+            ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
+            typeToCaseNodes.putIfAbsent(typeref, value);
+        }
+    }
+
+    @Override
+    public void onGlobalContextUpdated(SchemaContext context) {
+        currentSchema = context;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public void onChoiceCodecCreated(Class<?> choiceClass,
+            Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
+        ChoiceCodec<?> oldCodec = choiceCodecs.get(choiceClass);
+        checkState(oldCodec == null);
+        BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
+        ChoiceCodecImpl<?> newCodec = new ChoiceCodecImpl(delegate);
+        choiceCodecs.put(choiceClass, newCodec);
+        CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class, BindingCodec>) classToCaseRawCodec);
+        CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
+
+    }
+
+    @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
+    public void onDataContainerCodecCreated(Class<?> dataClass,
+            Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec) {
+        if (Augmentable.class.isAssignableFrom(dataClass)) {
+            AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
+            CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
+        }
+
+    }
+
+    private AugmentableCompositeCodec getAugmentableCodec(Class<?> dataClass) {
+        AugmentableCompositeCodec ret = augmentableCodecs.get(dataClass);
+        if (ret != null) {
+            return ret;
+        }
+        ret = new AugmentableCompositeCodec(dataClass);
+        augmentableCodecs.put(dataClass, ret);
+        return ret;
+    }
+
+    private static abstract class IntermediateCodec<T> implements //
+            DomCodec<T>, Delegator<BindingCodec<Map<QName, Object>, Object>> {
+
+        private final BindingCodec<Map<QName, Object>, Object> delegate;
+
+        @Override
+        public BindingCodec<Map<QName, Object>, Object> getDelegate() {
+            return delegate;
+        }
+
+        public IntermediateCodec(BindingCodec<Map<QName, Object>, Object> delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public Node<?> serialize(ValueWithQName<T> input) {
+            Map<QName, Object> intermediateOutput = delegate.serialize(input);
+            return toNode(intermediateOutput);
+        }
+    }
+
+    private static class IdentifierCodecImpl<T extends Identifier<?>> //
+            extends IntermediateCodec<T> //
+            implements IdentifierCodec<T> {
+
+        public IdentifierCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+            super(delegate);
+        }
+
+        @Override
+        public ValueWithQName<T> deserialize(Node<?> input) {
+            QName qname = input.getNodeType();
+            @SuppressWarnings("unchecked")
+            T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
+            return new ValueWithQName<T>(qname, value);
+        }
+
+        @Override
+        public CompositeNode serialize(ValueWithQName<T> input) {
+            return (CompositeNode) super.serialize(input);
+        }
+    }
+
+    private static class DataContainerCodecImpl<T extends DataContainer> //
+            extends IntermediateCodec<T> //
+            implements DataContainerCodec<T> {
+
+        public DataContainerCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+            super(delegate);
+        }
+
+        @Override
+        public ValueWithQName<T> deserialize(Node<?> input) {
+            if (input == null) {
+                return null;
+            }
+            QName qname = input.getNodeType();
+            @SuppressWarnings("unchecked")
+            T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
+            return new ValueWithQName<T>(qname, value);
+        }
+
+        @Override
+        public CompositeNode serialize(ValueWithQName<T> input) {
+            return (CompositeNode) super.serialize(input);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
+            Delegator<BindingCodec> {
+        private final boolean augmenting;
+        private BindingCodec delegate;
+
+        private final Set<String> validNames;
+        private final Set<QName> validQNames;
+        private ChoiceCaseNode schema;
+
+        public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+            this.delegate = NOT_READY_CODEC;
+            this.schema = caseNode;
+            validNames = new HashSet<>();
+            validQNames = new HashSet<>();
+            for (DataSchemaNode node : caseNode.getChildNodes()) {
+                QName qname = node.getQName();
+                validQNames.add(qname);
+                validNames.add(qname.getLocalName());
+            }
+            augmenting = caseNode.isAugmenting();
+        }
+
+        @Override
+        public ValueWithQName<T> deserialize(Node<?> input) {
+            throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+        }
+
+        @Override
+        public CompositeNode serialize(ValueWithQName<T> input) {
+            throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+        }
+
+        public BindingCodec getDelegate() {
+            return delegate;
+        }
+
+        public void setDelegate(BindingCodec delegate) {
+            this.delegate = delegate;
+        }
+
+        public ChoiceCaseNode getSchema() {
+            return schema;
+        }
+
+        @Override
+        public boolean isAcceptable(Node<?> input) {
+            if (false == (input instanceof CompositeNode)) {
+                if (augmenting) {
+                    return checkAugmenting((CompositeNode) input);
+                } else {
+                    return checkLocal((CompositeNode) input);
+                }
+            }
+            return false;
+        }
+
+        private boolean checkLocal(CompositeNode input) {
+            QName parent = input.getNodeType();
+            for (Node<?> childNode : input.getChildren()) {
+                QName child = childNode.getNodeType();
+                if (false == Objects.equals(parent.getNamespace(), child.getNamespace())) {
+                    continue;
+                }
+                if (false == Objects.equals(parent.getRevision(), child.getRevision())) {
+                    continue;
+                }
+                if (validNames.contains(child.getLocalName())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean checkAugmenting(CompositeNode input) {
+            for (Node<?> child : input.getChildren()) {
+                if (validQNames.contains(child.getNodeType())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private static class ChoiceCodecImpl<T> implements ChoiceCodec<T> {
+
+        private final BindingCodec<Map<QName, Object>, Object> delegate;
+
+        @SuppressWarnings("rawtypes")
+        private final Map<Class, ChoiceCaseCodecImpl<?>> cases = new WeakHashMap<>();
+
+        private final CaseCompositeNodeMapFacade CompositeToCase;
+
+        public ChoiceCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+            this.delegate = delegate;
+            this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
+        }
+
+        @Override
+        public ValueWithQName<T> deserialize(Node<?> input) {
+            throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+        }
+
+        @Override
+        public Node<?> serialize(ValueWithQName<T> input) {
+            throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+        }
+
+        public CaseCompositeNodeMapFacade getCompositeToCase() {
+            return CompositeToCase;
+        }
+
+        public Map<Class, ChoiceCaseCodecImpl<?>> getCases() {
+            return cases;
+        }
+
+        public BindingCodec<Map<QName, Object>, Object> getDelegate() {
+            return delegate;
+        }
+
+    }
+
+    @SuppressWarnings("rawtypes")
+    private class CaseClassMapFacade extends MapFacadeBase {
+
+        @Override
+        public Set<java.util.Map.Entry<Class, BindingCodec<Object, Object>>> entrySet() {
+            return null;
+        }
+
+        @Override
+        public BindingCodec get(Object key) {
+            if (key instanceof Class) {
+                Class cls = (Class) key;
+                bindingClassEncountered(cls);
+                ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
+                return caseCodec.getDelegate();
+            }
+            return null;
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
+
+        final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
+
+        public CaseCompositeNodeMapFacade(Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
+            this.choiceCases = choiceCases;
+        }
+
+        @Override
+        public Set<java.util.Map.Entry<CompositeNode, BindingCodec>> entrySet() {
+            return null;
+        }
+
+        @Override
+        public BindingCodec get(Object key) {
+            if (false == (key instanceof CompositeNode)) {
+                return null;
+            }
+            for (java.util.Map.Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
+                ChoiceCaseCodecImpl<?> codec = entry.getValue();
+                if (codec.isAcceptable((CompositeNode) key)) {
+                    return codec.getDelegate();
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * This map is used as only facade for {@link BindingCodec} in different
+     * classloaders to retrieve codec dynamicly based on provided key.
+     * 
+     * @param <T>
+     *            Key type
+     */
+    @SuppressWarnings("rawtypes")
+    private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec> {
+
+        @Override
+        public boolean containsKey(Object key) {
+            return get(key) != null;
+        }
+
+        @Override
+        public void clear() {
+            throw notModifiable();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return super.equals(obj);
+        }
+
+        @Override
+        public BindingCodec remove(Object key) {
+            return null;
+        }
+
+        @Override
+        public int size() {
+            return 0;
+        }
+
+        @Override
+        public Collection<BindingCodec> values() {
+            return null;
+        }
+
+        private UnsupportedOperationException notModifiable() {
+            return new UnsupportedOperationException("Not externally modifiable.");
+        }
+
+        @Override
+        public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec value) {
+            throw notModifiable();
+        }
+
+        @Override
+        public void putAll(Map<? extends T, ? extends BindingCodec> m) {
+            throw notModifiable();
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return false;
+        }
+
+        @Override
+        public Set<T> keySet() {
+            return null;
+        }
+
+        @Override
+        public Set<java.util.Map.Entry<T, BindingCodec>> entrySet() {
+            return null;
+        }
+
+        @Override
+        public boolean containsValue(Object value) {
+            return false;
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private class AugmentableCompositeCodec implements BindingCodec {
+
+        private final Class augmentableType;
+
+        Map<Class, BindingCodec> rawAugmentationCodecs = new WeakHashMap<>();
+
+        public AugmentableCompositeCodec(Class type) {
+            checkArgument(Augmentable.class.isAssignableFrom(type));
+            augmentableType = type;
+        }
+
+        @Override
+        public Object serialize(Object input) {
+            if (input instanceof Augmentable<?>) {
+
+                Map<Class, Augmentation> augmentations = getAugmentations(input);
+                return serializeImpl(augmentations);
+            }
+            return null;
+        }
+
+        private Map<Class, Augmentation> getAugmentations(Object input) {
+            Field augmentationField;
+            try {
+                augmentationField = input.getClass().getDeclaredField("augmentation");
+                augmentationField.setAccessible(true);
+                Map<Class, Augmentation> augMap = (Map<Class, Augmentation>) augmentationField.get(input);
+                return augMap;
+            } catch (NoSuchFieldException e) {
+
+            } catch (SecurityException e) {
+
+            } catch (IllegalArgumentException e) {
+
+            } catch (IllegalAccessException e) {
+
+            }
+            return Collections.emptyMap();
+        }
+
+        private List serializeImpl(Map<Class, Augmentation> input) {
+            List ret = new ArrayList<>();
+            for (Entry<Class, Augmentation> entry : input.entrySet()) {
+                BindingCodec codec = getRawCodecForAugmentation(entry.getKey());
+                List output = (List) codec.serialize(new ValueWithQName(null, entry.getValue()));
+                ret.addAll(output);
+            }
+            return ret;
+        }
+
+        private BindingCodec getRawCodecForAugmentation(Class key) {
+            BindingCodec ret = rawAugmentationCodecs.get(key);
+            if (ret != null) {
+                return ret;
+            }
+            try {
+                Class<? extends BindingCodec> retClass = generator.augmentationTransformerFor(key);
+                ret = retClass.newInstance();
+                rawAugmentationCodecs.put(key, ret);
+                return ret;
+            } catch (InstantiationException e) {
+
+            } catch (IllegalAccessException e) {
+
+            }
+            return null;
+        }
+
+        @Override
+        public Map<Class, Augmentation> deserialize(Object input) {
+            Map<Class, Augmentation> ret = new HashMap<>();
+            if (input instanceof CompositeNode) {
+                for (Entry<Class, BindingCodec> codec : rawAugmentationCodecs.entrySet()) {
+                    Augmentation value = (Augmentation) codec.getValue().deserialize(input);
+                    if (value != null) {
+                        ret.put(codec.getKey(), value);
+                    }
+                }
+            }
+            return ret;
+        }
+
+        public Map<Class, BindingCodec> getRawAugmentationCodecs() {
+            return rawAugmentationCodecs;
+        }
+
+        public void setRawAugmentationCodecs(Map<Class, BindingCodec> rawAugmentationCodecs) {
+            this.rawAugmentationCodecs = rawAugmentationCodecs;
+        }
+
+        public Class getAugmentableType() {
+            return augmentableType;
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
+
+        private BindingCodec delegate;
+
+        @Override
+        public BindingCodec getDelegate() {
+            if (delegate == null) {
+                throw new IllegalStateException("Codec not initialized yet.");
+            }
+            return delegate;
+        }
+
+        @Override
+        public Object deserialize(Object input) {
+            return getDelegate().deserialize(input);
+        }
+
+        @Override
+        public Object serialize(Object input) {
+            return getDelegate().serialize(input);
+        }
+    }
+}
\ 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/RuntimeGeneratedMappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend
new file mode 100644 (file)
index 0000000..4614c60
--- /dev/null
@@ -0,0 +1,218 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+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.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.common.QName
+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
+import com.google.common.collect.HashMultimap
+import com.google.common.util.concurrent.SettableFuture
+import java.util.concurrent.Future
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.LazyGeneratedCodecRegistry
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService
+import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
+import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec
+import org.opendaylight.yangtools.binding.generator.util.Types
+
+class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener {
+
+    @Property
+    ClassPool pool;
+
+    private static val LOG = LoggerFactory.getLogger(RuntimeGeneratedMappingServiceImpl);
+
+    @Property
+    extension TransformerGenerator binding;
+
+    @Property
+    extension LazyGeneratedCodecRegistry registry;
+
+    @Property
+    val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
+
+    @Property
+    val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+
+    @Property
+    val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
+
+    val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
+
+    val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
+
+    override onGlobalContextUpdated(SchemaContext arg0) {
+        recreateBindingContext(arg0);
+        registry.onGlobalContextUpdated(arg0);
+    }
+
+    def recreateBindingContext(SchemaContext schemaContext) {
+        val newBinding = new BindingGeneratorImpl();
+        newBinding.generateTypes(schemaContext);
+
+        for (entry : newBinding.moduleContexts.entrySet) {
+
+            registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
+
+            //val module = entry.key;
+            val context = entry.value;
+            updateBindingFor(context.childNodes, schemaContext);
+            updateBindingFor(context.cases, schemaContext);
+            
+
+            val typedefs = context.typedefs;
+            for (typedef : typedefs.values) {
+                binding.typeDefinitions.put(typedef, typedef as GeneratedType);
+            }
+            val augmentations = context.augmentations;
+            for (augmentation : augmentations) {
+                binding.typeToDefinition.put(augmentation, augmentation);
+            }
+            
+            binding.typeToAugmentation.putAll(context.typeToAugmentation);
+        }
+    }
+
+    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 = toDataDom(entry.key)
+        val data = toCompositeNodeImpl(entry.value);
+        return new SimpleEntry(key, data);
+    }
+
+    private def CompositeNode toCompositeNodeImpl(DataObject object) {
+        val cls = object.implementedInterface;
+        waitForSchema(cls);
+        val codec = registry.getCodecForDataObject(cls) as DataContainerCodec<DataObject>;
+        val ret = codec.serialize(new ValueWithQName(null, object));
+        return ret as CompositeNode;
+    }
+
+    private def waitForSchema(Class<? extends DataContainer> class1) {
+        val ref = Types.typeForClass(class1);
+        getSchemaWithRetry(ref);
+    }
+
+    override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> path) {
+        for (arg : path.path) {
+            waitForSchema(arg.type);
+        }
+        return registry.instanceIdentifierCodec.serialize(path);
+    }
+
+    override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
+        if (node == null) {
+            return null;
+        }
+        val targetType = path.targetType
+        val transformer = registry.getCodecForDataObject(targetType);
+        val ret = transformer.deserialize(node)?.value as DataObject;
+        return ret;
+    }
+
+    private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+        for (entry : map.entrySet) {
+            val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+            //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
+            if (schemaNode != null) {
+                typeToSchemaNode.put(entry.value, schemaNode);
+                typeToDefinition.put(entry.value, entry.value);
+                updatePromisedSchemas(entry.value, schemaNode);
+            }
+        }
+    }
+
+    public def void start() {
+        binding = new TransformerGenerator(pool);
+        registry = new LazyGeneratedCodecRegistry()
+        registry.generator = binding
+
+        //binding.staticFieldsInitializer = registry
+        binding.listener = registry
+        binding.typeToDefinition = typeToDefinition
+        binding.typeToSchemaNode = typeToSchemaNode
+        binding.typeDefinitions = typeDefinitions
+
+    }
+
+    private def getTypeDefinition(Type type) {
+        val typeDef = typeToDefinition.get(type);
+        if (typeDef !== null) {
+            return typeDef;
+        }
+        return type.getTypeDefInFuture.get();
+    }
+
+    private def Future<GeneratedTypeBuilder> getTypeDefInFuture(Type type) {
+        val future = SettableFuture.<GeneratedTypeBuilder>create()
+        promisedTypeDefinitions.put(type, future);
+        return future;
+    }
+
+    private def void updatePromisedTypeDefinitions(GeneratedTypeBuilder builder) {
+        val futures = promisedTypeDefinitions.get(builder);
+        if (futures === null || futures.empty) {
+            return;
+        }
+        for (future : futures) {
+            future.set(builder);
+        }
+        promisedTypeDefinitions.removeAll(builder);
+    }
+
+    private def getSchemaWithRetry(Type type) {
+        val typeDef = typeToSchemaNode.get(type);
+        if (typeDef !== null) {
+            return typeDef;
+        }
+        return type.getSchemaInFuture.get();
+    }
+
+    private def Future<SchemaNode> getSchemaInFuture(Type type) {
+        val future = SettableFuture.<SchemaNode>create()
+        promisedSchemas.put(type, future);
+        return future;
+    }
+
+    private def void updatePromisedSchemas(Type builder, SchemaNode schema) {
+        val ref = new ReferencedTypeImpl(builder.packageName, builder.name);
+        val futures = promisedSchemas.get(ref);
+        if (futures === null || futures.empty) {
+            return;
+        }
+        for (future : futures) {
+            future.set(schema);
+        }
+        promisedSchemas.removeAll(builder);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/StaticFieldInitializer.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/StaticFieldInitializer.java
new file mode 100644 (file)
index 0000000..e5b36e1
--- /dev/null
@@ -0,0 +1,6 @@
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+public interface StaticFieldInitializer {
+
+    void initializeStaticFields(Class<?> cls);
+}
index 2136572aa3240117ced443e180acc8b6c26d68be..8e059aa22ed4e8ec1946afc18154b5fe9a38ded6 100644 (file)
@@ -9,9 +9,9 @@ import java.util.Map
 import org.opendaylight.yangtools.yang.common.QName
 import javassist.CtField
 import static javassist.Modifier.*
+import static org.opendaylight.controller.sal.binding.dom.serializer.impl.CodecMapping.*
 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
@@ -22,7 +22,6 @@ 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
@@ -31,13 +30,21 @@ 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
 import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
 import java.security.ProtectionDomain
 import java.io.File
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import java.util.Map.Entry
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.Augmentation
+import java.util.Iterator
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+import java.util.concurrent.ConcurrentHashMap
 
 class TransformerGenerator {
 
@@ -46,6 +53,7 @@ class 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 INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
 
     //public static val DECIMAL = Types.typeForClass(Decimal);
     public static val LONG = Types.typeForClass(Long);
@@ -53,36 +61,39 @@ class TransformerGenerator {
     val ClassPool classPool
     val extension JavassistUtils utils;
 
-    CtClass ctTransformator
+    CtClass BINDING_CODEC
 
     CtClass ctQName
 
     @Property
     var File classFileCapturePath;
 
+    @Property
+    var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
 
     @Property
-    var Map<Type, Type> typeDefinitions;
+    var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
 
     @Property
-    var Map<Type, GeneratedTypeBuilder> typeToDefinition
+    var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
 
     @Property
-    var Map<Type, SchemaNode> typeToSchemaNode
+    var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
 
-    val Map<Class<?>, Class<?>> generatedClasses = new WeakHashMap();
+    @Property
+    var GeneratorListener listener;
 
     public new(ClassPool pool) {
         classPool = pool;
         utils = new JavassistUtils(pool)
 
-        ctTransformator = BindingCodec.asCtClass;
+        BINDING_CODEC = 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);
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val ret = getGeneratedClass(inputType)
             if (ret !== null) {
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
@@ -90,60 +101,148 @@ class TransformerGenerator {
             val node = typeToSchemaNode.get(ref)
             val typeSpecBuilder = typeToDefinition.get(ref)
             val typeSpec = typeSpecBuilder.toInstance();
-            val newret = generateTransformerFor(inputType, typeSpec, node)
-            generatedClasses.put(inputType, newret);
+            val newret = generateTransformerFor(inputType, typeSpec, node);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val ret = getGeneratedClass(inputType)
+            if (ret !== null) {
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ref = Types.typeForClass(inputType)
+            val node = typeToAugmentation.get(ref)
+            val typeSpecBuilder = typeToDefinition.get(ref)
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val ret = getGeneratedClass(inputType)
+            if (ret !== null) {
+                return ret as Class<? extends BindingCodec<Object, Object>>;
+            }
+            val ref = Types.typeForClass(inputType)
+            val typeSpecBuilder = typeToDefinition.get(ref)
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateCaseCodec(inputType, typeSpec, node);
+            return newret as Class<? extends BindingCodec<Object, Object>>;
+        ]
+    }
+
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
+        return withClassLoaderAndLock(parentType.classLoader, lock) [ |
+            val inputName = parentType.name + "Key";
+            val inputType = loadClassWithTCCL(inputName);
+            val ret = getGeneratedClass(inputType)
+            if (ret !== null) {
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ref = Types.typeForClass(parentType)
+            val node = typeToSchemaNode.get(ref) as ListSchemaNode
+            val typeSpecBuilder = typeToDefinition.get(ref)
+            val typeSpec = typeSpecBuilder.identifierDefinition;
+            val newret = generateKeyTransformerFor(inputType, typeSpec, node);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def getIdentifierDefinition(GeneratedTypeBuilder builder) {
+        val inst = builder.toInstance
+        val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
+        return keyMethod.returnType as GeneratedTransferObject
+    }
+
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val ret = getGeneratedClass(inputType)
+            if (ret !== null) {
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ref = Types.typeForClass(inputType)
+            val node = typeToSchemaNode.get(ref) as ListSchemaNode
+            val typeSpecBuilder = typeToDefinition.get(ref)
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateKeyTransformerFor(inputType, typeSpec, node);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
     }
 
     private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
-        return withClassLoader(inputType.classLoader) [ |
-            val transformer = generatedClasses.get(inputType);
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val transformer = getGeneratedClass(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) {
+    private def Class getGeneratedClass(Class<? extends Object> cls) {
+
+        try {
+            return loadClassWithTCCL(cls.codecClassName)
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    private 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);
 
     }
 
     private def Class<?> getValueSerializer(GeneratedTransferObject type) {
         val cls = loadClassWithTCCL(type.resolvedName);
-        val transformer = generatedClasses.get(cls);
+        val transformer = cls.generatedClass;
         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)
+            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = typeSpec.allProperties;
-            val ctCls = createClass(inputType.transformatorFqn) [
+            val ctCls = createClass(inputType.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticQNameField(node.QName);
-                implementsType(ctTransformator)
+                implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
                         {
-                        
-                            return null;
+                            Â«QName.name» _resultName;
+                            if($1 != null) {
+                                _resultName = Â«QName.name».create($1,QNAME.getLocalName());
+                            } else {
+                                _resultName = QNAME;
+                            }
+                            java.util.List _childNodes = new java.util.ArrayList();
+                            Â«inputType.name» value = («inputType.name») $2;
+                            Â«FOR key : node.keyDefinition»
+                                Â«val propertyName = key.getterName»
+                                Â«val keyDef = node.getDataChildByName(key)»
+                                Â«val property = properties.get(propertyName)»
+                                Â«serializeProperty(keyDef, property, propertyName)»;
+                            Â«ENDFOR»
+                            return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
                         }
                     '''
                 ]
@@ -160,7 +259,7 @@ class TransformerGenerator {
                                 Â«val propertyName = key.getterName»
                                 Â«val keyDef = node.getDataChildByName(key)»
                                 Â«val property = properties.get(propertyName)»
-                                Â«deserializeProperty(keyDef, property.returnType, property)»;
+                                Â«deserializeProperty(keyDef, property, propertyName)»;
                             Â«ENDFOR»
                             Â«inputType.name» _value = new Â«inputType.name»(«node.keyDefinition.keyConstructorList»);
                             return _value;
@@ -169,7 +268,12 @@ class TransformerGenerator {
                 ]
                 method(Object, "serialize", Object) [
                     body = '''
-                        return toDomStatic(QNAME,$1);
+                        {
+                            java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
+                            Â«QName.name» _localQName = («QName.name») _input.getKey();
+                            Â«inputType.name» _keyValue = («inputType.name») _input.getValue();
+                            return toDomStatic(_localQName,_keyValue);
+                        }
                     '''
                 ]
                 method(Object, "deserialize", Object) [
@@ -179,29 +283,95 @@ class TransformerGenerator {
                 ]
             ]
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            log.info("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
         } catch (Exception e) {
-            processException(inputType,e);
+            processException(inputType, e);
             return null;
         }
     }
 
-    private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
-        GeneratedType typeSpec, SchemaNode node) {
+    private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
+        ChoiceCaseNode node) {
         try {
-            log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
-            val ctCls = createClass(typeSpec.transformatorFqn) [
+            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                implementsType(BINDING_CODEC)
                 staticQNameField(inputType);
-                implementsType(ctTransformator)
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                method(Object, "toDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            Â«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) _childNodes;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        {
+                            java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+                            Â«QName.name» _localName = QNAME;
+                            if(_input.getKey() != null) {
+                                _localName = («QName.name») _input.getKey();
+                            }
+                            return toDomStatic(_localName,_input.getValue());
+                        }
+                    '''
+                ]
+                method(Object, "fromDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = deserializeBody(type, node)
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''
+                        {
+                            
+                            return fromDomStatic(QNAME,$1);
+                        }
+                    '''
+                ]
+            ]
+
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            return ret as Class<? extends BindingCodec<Object, Object>>;
+        } catch (Exception e) {
+            processException(inputType, e);
+            return null;
+        }
+    }
+
+    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);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = serializeBodyFacade(typeSpec, node)
                 ]
                 method(Object, "serialize", Object) [
                     body = '''
-                        return toDomStatic(QNAME,$1);
+                        {
+                            java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+                            Â«QName.name» _localName = QNAME;
+                            if(_input.getKey() != null) {
+                                _localName = («QName.name») _input.getKey();
+                            }
+                            return toDomStatic(_localName,_input.getValue());
+                        }
                     '''
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
@@ -215,55 +385,159 @@ class TransformerGenerator {
                 ]
             ]
 
-            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+            listener?.onDataContainerCodecCreated(inputType, ret);
+            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            return ret;
         } catch (Exception e) {
-            processException(inputType,e);
+            processException(inputType, e);
             return null;
         }
     }
-    
-    
-    private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
-        GeneratedType typeSpec, ChoiceNode node) {
+
+    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 ctCls = createClass(typeSpec.transformatorFqn) [
+            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);
-                implementsType(ctTransformator)
+                staticQNameField(inputType);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
-                        return null;
+                        {
+                            //System.out.println("Qname " + $1);
+                            //System.out.println("Value " + $2);
+                            Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
+                            java.util.List _childNodes = new java.util.ArrayList();
+                            Â«type.resolvedName» value = («type.resolvedName») $2;
+                            Â«FOR child : node.childNodes»
+                                Â«var signature = properties.getFor(child)»
+                                //System.out.println("«signature.key»" + value.«signature.key»());
+                                Â«serializeProperty(child, signature.value, signature.key)»
+                            Â«ENDFOR»
+                            return ($r) _childNodes;
+                        }
                     '''
                 ]
                 method(Object, "serialize", Object) [
                     body = '''
-                        return null;
+                        {
+                        java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+                        Â«QName.name» _localName = QNAME;
+                        if(_input.getKey() != null) {
+                            _localName = («QName.name») _input.getKey();
+                        }
+                        return toDomStatic(_localName,_input.getValue());
+                        }
                     '''
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
-                        return null;
+                        {
+                            Â«QName.name» _localQName = QNAME;
+                            
+                            if($2 == null) {
+                            return null;
+                            }
+                            java.util.Map _compositeNode = (java.util.Map) $2;
+                            ////System.out.println(_localQName + " " + _compositeNode);
+                            Â«type.builderName» _builder = new Â«type.builderName»();
+                            Â«FOR child : node.childNodes»
+                                Â«val signature = properties.getFor(child)»
+                                Â«deserializeProperty(child, signature.value, signature.key)»
+                                
+                                _builder.«signature.key.toSetter»(«signature.key»);
+                            Â«ENDFOR»
+                            return _builder.build();
+                        }
                     '''
                 ]
                 method(Object, "deserialize", Object) [
                     body = '''
-                        return null;
+                        return fromDomStatic(QNAME,$1);
                     '''
                 ]
             ]
 
-            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+            listener?.onDataContainerCodecCreated(inputType, ret);
+            return ret;
         } catch (Exception e) {
-            processException(inputType,e);
+            processException(inputType, e);
+            return null;
+        }
+    }
+
+    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");
+                //staticQNameField(inputType);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, CLASS_TO_CASE_MAP, Map)
+                staticField(it, COMPOSITE_TO_CASE, Map)
+                //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
+                implementsType(BINDING_CODEC)
+                method(List, "toDomStatic", QName, Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            if($2 == null) {
+                                return null;
+                            }
+                            Â«DataObject.name» _baValue = («DataObject.name») $2;
+                            Class _baClass = _baValue.getImplementedInterface();
+                            Â«BINDING_CODEC.name» _codec =  Â«CLASS_TO_CASE_MAP».get(_baClass);
+                            if(_codec == null) {
+                                return null;
+                            }
+                            java.util.Map.Entry _input = new Â«SimpleEntry.name»($1,_baValue);
+                            return (java.util.List) _codec.serialize(_input);
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    body = '''
+                        throw new Â«UnsupportedOperationException.name»("Direct invocation not supported.");
+                    '''
+                ]
+                method(Object, "fromDomStatic", QName, Map) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    body = '''
+                        {
+                            Â«BINDING_CODEC.name» _codec = («BINDING_CODEC.name») Â«COMPOSITE_TO_CASE».get($2);
+                            if(_codec != null) {
+                                return _codec.deserialize(new Â«SimpleEntry.name»($1,$2));
+                            }
+                            return null;
+                        }
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    body = '''
+                        throw new Â«UnsupportedOperationException.name»("Direct invocation not supported.");
+                    '''
+                ]
+            ]
+
+            val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            listener?.onChoiceCodecCreated(inputType, ret);
+            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            return ret;
+        } catch (Exception e) {
+            processException(inputType, e);
             return null;
         }
     }
-    
 
     private def keyConstructorList(List<QName> qnames) {
         val names = new TreeSet<String>()
@@ -302,7 +576,6 @@ class TransformerGenerator {
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
             Â«type.builderName» _builder = new Â«type.builderName»();
-            
             return _builder.build();
         }
     '''
@@ -317,6 +590,7 @@ class TransformerGenerator {
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeKey(type, node)»
             Â«deserializeDataNodeContainerBody(type, node)»
+            Â«deserializeAugmentations»
             return _builder.build();
         }
     '''
@@ -330,6 +604,7 @@ class TransformerGenerator {
             java.util.Map _compositeNode = (java.util.Map) $2;
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeDataNodeContainerBody(type, node)»
+            Â«deserializeAugmentations»
             return _builder.build();
         }
     '''
@@ -337,12 +612,15 @@ class TransformerGenerator {
     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;
+            ////System.out.println(_localQName + " " + _compositeNode);
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeDataNodeContainerBody(type, node)»
+            Â«deserializeAugmentations»
             return _builder.build();
         }
     '''
@@ -351,87 +629,106 @@ class TransformerGenerator {
         deserializeNodeContainerBodyImpl(type, type.allProperties, node);
     }
 
-    private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, MethodSignature> properties,
+    private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
         DataNodeContainer node) {
         val ret = '''
             Â«FOR child : node.childNodes.filter[!augmenting]»
                 Â«val signature = properties.getFor(child)»
-                Â«deserializeProperty(child, signature.returnType, signature)»
-                _builder.«signature.name.toSetter»(«signature.name»);
+                Â«deserializeProperty(child, signature.value, signature.key)»
+                
+                _builder.«signature.key.toSetter»(«signature.key»);
             Â«ENDFOR»
         '''
         return ret;
     }
 
+    def deserializeAugmentations() '''
+        java.util.Map _augmentation = (java.util.Map) Â«AUGMENTATION_CODEC».deserialize(_compositeNode);
+        if(_augmentation != null) {
+            Â«Iterator.name» _entries = _augmentation.entrySet().iterator();
+            while(_entries.hasNext()) {
+                java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
+                //System.out.println("Aug. key:" + _entry.getKey());
+                Class _type = (Class) _entry.getKey();
+                Â«Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
+                _builder.addAugmentation(_type,_value);
+            }
+        }
+    '''
+
     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.
+        String propertyName) '''
+        java.util.List _dom_«propertyName» = _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) {
+        ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
+        java.util.List Â«propertyName» = new java.util.ArrayList();
+        if(_dom_«propertyName» != null) {
             java.util.List _serialized = new java.util.ArrayList();
-            java.util.Iterator _iterator = _dom_«property.name».iterator();
+            java.util.Iterator _iterator = _dom_«propertyName».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);
+                ////System.out.println("  item" + _listItem);
+                Object _value = Â«type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+                ////System.out.println("  value" + _value);
+                Â«propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
             }
         }
         
-        //System.out.println(" list" + Â«property.name»);
+        ////System.out.println(" list" + Â«propertyName»);
     '''
 
     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.
+        String propertyName) '''
+        java.util.List _dom_«propertyName» = _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 Â«propertyName» = new java.util.ArrayList();
+        if(_dom_«propertyName» != null) {
             java.util.List _serialized = new java.util.ArrayList();
-            java.util.Iterator _iterator = _dom_«property.name».iterator();
+            java.util.Iterator _iterator = _dom_«propertyName».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);
+                    Â«propertyName».add(_value);
                 }
                 _hasNext = _iterator.hasNext();
             }
         }
     '''
 
-    private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) '''
-        java.util.List _dom_«property.name»_list = 
+    private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
+        java.util.List _dom_«propertyName»_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")»;
+        Â«type.resolvedName» Â«propertyName» = null;
+        if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+            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")»;
         }
     '''
 
     private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
-        MethodSignature property) '''
-        java.util.List _dom_«property.name»_list = 
+        String propertyName) '''
+        java.util.List _dom_«propertyName»_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) {
+        Â«type.resolvedName» Â«propertyName» = null;
+        if(_dom_«propertyName»_list != null && _dom_«propertyName»_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»);
+            java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
+            Â«propertyName» =  Â«type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
         }
     '''
 
+    private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = Â«type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+    '''
+
     private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
-        («type.resolvedName») Â«type.valueSerializer.name».fromDomValue(«domParameter»);
+        («type.resolvedName») Â«type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
     '''
 
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
@@ -445,9 +742,10 @@ class TransformerGenerator {
                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
-            val ctCls = createClass(typeSpec.transformatorFqn) [
+            val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                implementsType(ctTransformator)
+                implementsType(BINDING_CODEC)
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 implementsType(BindingDeserializer.asCtClass)
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
@@ -459,10 +757,11 @@ class TransformerGenerator {
                                 return null;
                             }
                             Â«typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
-                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
                             Â«returnType.resolvedName» _value =  _encapsulatedValue.getValue();
-                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
-                            return _value;
+                            ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+                            Object _domValue = Â«serializeValue(returnType, "_value")»;
+                            return _domValue;
                         }
                     '''
                 ]
@@ -477,7 +776,7 @@ class TransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
                         {
-                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
@@ -497,10 +796,10 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            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 {}",inputType,e);
+            log.error("Cannot compile DOM Codec for {}", inputType, e);
             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
             exception.addSuppressed(e);
             throw exception;
@@ -509,10 +808,10 @@ class TransformerGenerator {
     }
 
     private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
-        log.info("Generating Dummy DOM Codec for {} with {}",object,object.classLoader)
-        return createClass(typeSpec.transformatorFqn) [
+        log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
+        return createClass(typeSpec.codecClassName) [
             //staticField(Map,"AUGMENTATION_SERIALIZERS");
-            implementsType(ctTransformator)
+            implementsType(BINDING_CODEC)
             implementsType(BindingDeserializer.asCtClass)
             method(Object, "toDomValue", Object) [
                 modifiers = PUBLIC + FINAL + STATIC
@@ -553,10 +852,10 @@ class TransformerGenerator {
     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) [
+            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                implementsType(ctTransformator)
+                implementsType(BINDING_CODEC)
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
@@ -591,49 +890,57 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}",inputType,ret)
+            log.info("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         } catch (CodeGenerationException e) {
-            throw new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
+            throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
         } catch (Exception e) {
-            log.error("Cannot compile DOM Codec for {}",inputType,e);
+            log.error("Cannot compile DOM Codec for {}", inputType, e);
             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
             exception.addSuppressed(e);
             throw exception;
         }
 
     }
-    
+
     def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
-        val cls = newClass.toClass(loader,domain);
-        if(classFileCapturePath !== null) {
+        val cls = newClass.toClass(loader, domain);
+        if (classFileCapturePath !== null) {
             newClass.writeFile(classFileCapturePath.absolutePath);
         }
+        listener?.onCodecCreated(cls);
         return cls;
     }
-    
+
     def debugWriteClass(CtClass class1) {
-        val path = class1.name.replace(".","/")+".class"
-        
-        val captureFile = new File(classFileCapturePath,path);
+        val path = class1.name.replace(".", "/") + ".class"
+
+        val captureFile = new File(classFileCapturePath, path);
         captureFile.createNewFile
-        
-        
+
     }
 
-    private def dispatch String deserializeValue(Type type, String domParameter) '''(«type.resolvedName») Â«domParameter»'''
+    private def dispatch String deserializeValue(Type type, String domParameter) {
+        if (INSTANCE_IDENTIFIER.equals(type)) {
+
+            return '''(«InstanceIdentifier.name») Â«INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
+        }
+
+        return '''(«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, Type type, String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = null;
     '''
 
     private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
-        MethodSignature property) {
-        _deserializeProperty(container, type.toInstance, property)
+        String propertyName) {
+        _deserializeProperty(container, type.toInstance, propertyName)
     }
 
     public static def toSetter(String it) {
@@ -647,84 +954,96 @@ class TransformerGenerator {
     }
 
     /* 
-    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 dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            Object domValue = Â«type.serializer».toDomStatic(QNAME,«propertyName»);
+            _childNodes.add(domValue);
         }
     '''
     */
     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
 
-    private def staticQNameField(CtClass it, Class node) {
+    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»")''')
+        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();
+            Â«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);
+            Â«serializeAugmentations»
+            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();
+            Â«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);
+            Â«serializeAugmentations»
+            return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
     '''
 
     private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
         {
-        Â«QName.name» resultName = Â«QName.name».create($1,QNAME.getLocalName());
-            java.util.List childNodes = new java.util.ArrayList();
+        Â«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);
+            Â«serializeAugmentations»
+            return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
     '''
 
     private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
         {
-        Â«QName.name» resultName = Â«QName.name».create($1,QNAME.getLocalName());
-            java.util.List childNodes = new java.util.ArrayList();
+        Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
+            java.util.List _childNodes = new java.util.ArrayList();
             Â«type.resolvedName» value = («type.resolvedName») $2;
-            return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+            return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
     '''
 
-
-    private def transformDataContainerBody(Map<String, MethodSignature> properties, DataNodeContainer node) {
+    private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
         val ret = '''
             Â«FOR child : node.childNodes.filter[!augmenting]»
                 Â«var signature = properties.getFor(child)»
-                Â«serializeProperty(child, signature.returnType, signature)»
+                //System.out.println("«signature.key»" + value.«signature.key»());
+                Â«serializeProperty(child, signature.value, signature.key)»
             Â«ENDFOR»
         '''
         return ret;
     }
-    
-    def MethodSignature getFor(Map<String,MethodSignature> map, DataSchemaNode node) {
+
+    def serializeAugmentations() '''
+        java.util.List _augmentations = (java.util.List) Â«AUGMENTATION_CODEC».serialize(value);
+        if(_augmentations != null) {
+            _childNodes.addAll(_augmentations);
+        }
+    '''
+
+    def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
         val sig = map.get(node.getterName);
-        if(sig == null) {
-            return map.get(node.booleanGetterName);
+        if (sig == null) {
+
+            return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
         }
-        return sig;
+        return new SimpleEntry(node.getterName, sig);
     }
 
     private static def String getBooleanGetterName(DataSchemaNode node) {
@@ -740,106 +1059,126 @@ class TransformerGenerator {
     }
 
     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();
+        String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            java.util.Iterator _iterator = Â«propertyName».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);
+                Object _domValue = Â«type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_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»();
+    private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
         
-        if(«property.name» != null) {
-            Â«QName.name» _qname = Â«QName.name».create(resultName,"«schema.QName.localName»");
-            Object _propValue = Â«serializeValue(type, property.name)»;
+        if(«propertyName» != null) {
+            Â«QName.name» _qname = Â«QName.name».create(_resultName,"«schema.QName.localName»");
+            Object _propValue = Â«serializeValue(type, propertyName)»;
             if(_propValue != null) {
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
-                childNodes.add(_domValue);
+                _childNodes.add(_domValue);
             }
         }
     '''
 
-    private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.name».toDomValue(«parameter»)'''
+    private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
+        resolvedName».toDomValue(«parameter»)'''
 
-    private def dispatch serializeValue(Type signature, String property) '''«property»'''
+    private def dispatch serializeValue(Type signature, String property) {
+        if (INSTANCE_IDENTIFIER == signature) {
+            return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
+        }
+        return '''«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();
+    private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
+        String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            Â«QName.name» _qname = Â«QName.name».create(_resultName,"«schema.QName.localName»");
+            java.util.Iterator _iterator = Â«propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                Object _propValue = Â«property.name»;
+                Object _propValue = Â«serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
-                childNodes.add(_domValue);
+                _childNodes.add(_domValue);
                 _hasNext = _iterator.hasNext();
             }
         }
     '''
 
+    private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
+        String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            java.util.List domValue = Â«type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            _childNodes.addAll(domValue);
+        }
+    '''
+
     /** 
      * 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, Type type, String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            Object domValue = Â«propertyName»;
+            _childNodes.add(domValue);
         }
     '''
 
     private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
-        MethodSignature property) {
-        serializeProperty(container, type.toInstance, property)
+        String propertyName) {
+        serializeProperty(container, type.toInstance, propertyName)
     }
 
     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.name».toDomStatic(QNAME,«property.name»);
-            childNodes.add(domValue);
+        String propertyName) '''
+        Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
+        if(«propertyName» != null) {
+            Object domValue = Â«type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            _childNodes.add(domValue);
         }
     '''
 
-
-
-    private def transformatorFqn(GeneratedType typeSpec) {
+    private def codecClassName(GeneratedType typeSpec) {
         return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
     }
 
-    private def transformatorFqn(Class typeSpec) {
+    private def codecClassName(Class typeSpec) {
         return '''«typeSpec.name»$Broker$Codec$DOM'''
     }
 
-    private def HashMap<String, MethodSignature> getAllProperties(GeneratedType type) {
-        val ret = new HashMap<String, MethodSignature>();
+    private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
+        val ret = new HashMap<String, Type>();
         type.collectAllProperties(ret);
         return ret;
     }
 
-    private def dispatch void collectAllProperties(GeneratedType type, Map<String, MethodSignature> set) {
+    private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
         for (definition : type.methodDefinitions) {
-            set.put(definition.name, definition);
+            set.put(definition.name, definition.returnType);
+        }
+        for (property : type.properties) {
+            set.put(property.getterName, property.returnType);
         }
-
         for (parent : type.implements) {
             parent.collectAllProperties(set);
         }
     }
 
-    private def dispatch void collectAllProperties(Type type, Map<String, MethodSignature> set) {
+    def String getGetterName(GeneratedProperty property) {
+        return "get" + property.name.toFirstUpper
+    }
+
+    private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
         // NOOP for generic type.
     }
 
@@ -847,22 +1186,24 @@ class TransformerGenerator {
         return type.asCtClass.name;
     }
 
+    def String getResolvedName(Class type) {
+        return type.asCtClass.name;
+    }
+
     def CtClass asCtClass(Type type) {
         val name = type.fullyQualifiedName
         val cls = loadClassWithTCCL(type.fullyQualifiedName)
         return cls.asCtClass;
     }
-    
-    
-    
-    private def dispatch processException(Class<?> inputType,CodeGenerationException e){
-        log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.",inputType);
+
+    private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
+        log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
         throw e;
     }
-    
-    private def dispatch processException(Class<?> inputType,Exception e){
-        log.error("Cannot compile DOM Codec for {}",inputType,e);
-        val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
+
+    private def dispatch processException(Class<?> inputType, Exception e) {
+        log.error("Cannot compile DOM Codec for {}", inputType, e);
+        val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
         throw exception;
     }
 
@@ -876,7 +1217,7 @@ class PropertyPair {
     Type type;
 
     @Property
-    MethodSignature signature;
+    Type returnType;
     @Property
     SchemaNode schemaNode;
 }
index 6e493057b240e2f7bcce4c2ebad267afbf9fb4c6..887ef82ca90c459d6ed4e8d12bc7c52903442919 100644 (file)
@@ -179,7 +179,7 @@ class NotifyTask implements Callable<Object> {
         try {
             listener.onNotification(notification);
         } catch (Exception e) {
-            log.error("Unhandled exception {} thrown by listener: {} Notification: {}", e, listener, notification);
+            log.error("Unhandled exception thrown by listener: {}", listener, e);
         }
         return null;
     }
index d8fbc70f8e26d70a1320688c1051cc9c20b74c0a..8e61c9b3eeb8c131d81d30c8446b460c297eda95 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
 import java.util.Map.Entry;
 
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -16,4 +17,6 @@ public interface BindingIndependentMappingService {
     org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
 
     DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+    
+    
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend
deleted file mode 100644 (file)
index a0e1c98..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-package org.opendaylight.controller.sal.binding.impl.connect.dom
-
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext
-import java.util.List
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
-import org.opendaylight.yangtools.sal.binding.model.api.Type
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import java.util.Map
-import org.opendaylight.yangtools.yang.model.api.SchemaPath
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
-import org.opendaylight.yangtools.binding.generator.util.Types
-import java.util.HashMap
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.binding.DataContainer
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
-import java.util.Collections
-import java.util.ArrayList
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.model.util.ExtendedType
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
-import com.google.common.collect.FluentIterable
-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) {
-        val ref = Types.typeForClass(cls);
-        return typeToSchemaNode.get(ref)?.QName;
-    }
-
-    def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) {
-        updateBindingFor(moduleBindingContext.childNodes, schemaContext);
-
-    }
-
-    def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
-        InstanceIdentifier<? extends DataObject> obj) {
-        val pathArguments = obj.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);
-    }
-
-    
-
-    def DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
-        if (node == null) {
-            return null;
-        }
-        val targetClass = identifier.targetType;
-        val classLoader = targetClass.classLoader;
-        val ref = Types.typeForClass(targetClass);
-        val targetType = typeToDefinition.get(ref);
-        val targetSchema = typeToSchemaNode.get(ref);
-        return node.toDataObject(classLoader, targetType.toInstance, targetSchema);
-
-    }
-
-    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 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);
-    }
-
-    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 = identifier.getSimpleValue(keydef, keyNode.type);
-            map.put(keydef, value.value);
-        }
-        return map;
-    }
-
-    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)
-        }
-    }
-
-    def CompositeNode toCompositeNode(DataContainer data) {
-        val type = data.implementedInterface;
-        val typeRef = Types.typeForClass(type);
-        val schemaNode = typeToSchemaNode.get(typeRef);
-        val generatedType = typeToDefinition.get(typeRef);
-
-        return data.toDataDom(schemaNode, generatedType);
-    }
-
-    private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node,
-        GeneratedTypeBuilder builder) {
-        val subnodes = data.toDataDomComponents(node);
-        return new CompositeNodeTOImpl(node.QName, null, subnodes);
-    }
-
-    private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node,
-        GeneratedTypeBuilder builder) {
-        val subnodes = data.toDataDomComponents(node);
-        return new CompositeNodeTOImpl(node.QName, null, subnodes);
-    }
-
-    private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node,
-        GeneratedTypeBuilder builder) {
-        val subnodes = data.toDataDomComponents(node);
-        return new CompositeNodeTOImpl(node.QName, null, subnodes);
-    }
-
-    private def List<Node<?>> toDataDomComponents(DataContainer data, DataNodeContainer node) {
-        val subnodes = new ArrayList<Node<?>>();
-        for (childNode : node.childNodes) {
-            val value = childNode.dataDomFromParent(data);
-            if (value !== null) {
-                subnodes.addAll(value);
-            }
-        }
-        return subnodes;
-    }
-
-    private def List<Node<?>> dataDomFromParent(DataSchemaNode node, DataContainer container) {
-        if (node.augmenting) {
-            return Collections.emptyList();
-        }
-        return dataDomFromParentImpl(node, container);
-    }
-
-    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) {
-        val value = container.getSimpleValue(node.QName, node.type);
-        if (value !== null) {
-            return Collections.<Node<?>>singletonList(value);
-        }
-        return Collections.emptyList();
-    }
-
-    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) {
-        val values = container.getSimpleValues(node);
-        if (values !== null) {
-            //val it = new ArrayList<Node<?>>();
-            //for (value : values) {
-            //}
-
-        }
-        return Collections.emptyList();
-    }
-
-    private def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
-        return Collections.emptyList();
-    }
-
-    private def dispatch List<Node<?>> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) {
-        val qname = node.QName;
-        val values = container.<List>getValue(qname, List) as List<? extends DataContainer>;
-        if (values === null) {
-            return Collections.emptyList;
-        }
-        val it = new ArrayList<Node<?>>();
-        for (value : values) {
-            add(value.toCompositeNode());
-        }
-
-        return it;
-    }
-
-    private def dispatch List<Node<?>> dataDomFromParentImpl(ChoiceNode node, DataContainer container) {
-    }
-
-    private def dispatch List<Node<?>> serializeValueImpl(List<?> list, GeneratedTypeBuilder builder,
-        ListSchemaNode node) {
-        val it = new ArrayList<Node<?>>();
-        for (value : list) {
-
-            val serVal = value.serializeValueImpl(builder, node);
-            if (serVal !== null) {
-                addAll(serVal);
-            }
-        }
-        return it;
-    }
-
-    public static def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
-        getSimpleValue(container, name, type.baseType);
-    }
-
-    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);
-    }
-
-    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);
-    }
-
-    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);
-    }
-
-    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);
-    }
-
-    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) {
-            clz = (object as DataContainer).implementedInterface;
-        }
-        val method = clz.getMethod(methodName);
-        if (method === null) {
-            return null;
-        }
-        val value = method.invoke(object);
-        if (value === null) {
-            return null;
-        }
-        if (type.isAssignableFrom(value.class)) {
-            return value  as T;
-        }
-        return value.getEncapsulatedValue(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;
-        }
-        return null;
-    }
-
-    private def dispatch List<Node<?>> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder,
-        SchemaNode node) {
-        return Collections.<Node<?>>singletonList(data.toDataDom(node, builder));
-    }
-
-    private def dispatch List<Node<?>> serializeValueImpl(Object object, GeneratedTypeBuilder builder,
-        SchemaNode node) {
-    }
-
-    def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) {
-
-        // Nasty reflection hack (for now)
-        val builderClass = loader.loadClass(type.builderFQN);
-        val builder = builderClass.newInstance;
-        val buildMethod = builderClass.getMethod("build");
-
-        node.fillDataObject(builder, loader, type, schema);
-
-        return buildMethod.invoke(builder) as DataObject;
-    }
-
-    private def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
-        ListSchemaNode schema) {
-
-        if (schema.keyDefinition !== null && !schema.keyDefinition.empty) {
-
-            val value = node.keyToBindingKey(loader, type, schema);
-            builder.setProperty("key", value);
-        }
-        node.fillBuilderFromContainer(builder,loader,type,schema);
-    }
-    
-    
-
-    private def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
-        ContainerSchemaNode schema) {
-        node.fillBuilderFromContainer(builder,loader,type,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;
-        val args = new ArrayList();
-        for (key : schema.keyDefinition) {
-            var keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName));
-            if (keyProperty == null) {
-                keyProperty = keyType.get(BindingGeneratorUtil.parseToValidParamName(key.localName));
-            }
-            val domKeyValue = node.getFirstSimpleByName(key);
-            val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType,
-                schema.getDataChildByName(key));
-            args.add(keyValue);
-        }
-        return ClassLoaderUtils.construct(constructor, args);
-    }
-
-    private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
-        LeafSchemaNode node2) {
-        deserializeSimpleValueImpl(node, loader, type, node2.type);
-    }
-
-    private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
-        LeafListSchemaNode node2) {
-        deserializeSimpleValueImpl(node, loader, type, node2.type);
-    }
-
-    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
-        ExtendedType definition) {
-        deserializeSimpleValueImpl(node, loader, type, definition.baseType);
-    }
-
-    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
-        StringTypeDefinition definition) {
-        if (type instanceof GeneratedTransferObject) {
-            val cls = loader.getClassForType(type);
-            val const = cls.getConstructor(String);
-            val str = String.valueOf(node.value);
-            return const.newInstance(str);
-        }
-        return node.value;
-    }
-
-    private def Class<?> getClassForType(ClassLoader loader, Type type) {
-        loader.loadClass(type.fullyQualifiedName);
-    }
-
-    private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
-        TypeDefinition definition) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    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>();
-        for (prop : key.properties) {
-            ret.put(prop.name, prop);
-        }
-        return ret;
-    }
-
-    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);
-    }
-
-    private def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
-
-    private def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
-
-}
-
-@Data
-class PropertyCapture {
-
-    @Property
-    val Type returnType;
-    @Property
-    val String name;
-
-}
index af18e9c0cb184a7d7060fd34e37c674fce1d28c9..f69e664ee8c764d3eb8be718ed88932ff1474f50 100644 (file)
@@ -6,6 +6,7 @@ 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.RuntimeGeneratedMappingServiceImpl;
 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;
@@ -42,6 +43,7 @@ public class ConnectorActivator implements Provider, ServiceTrackerCustomizer<Br
     public void onSessionInitiated(ProviderSession session) {
 
         RuntimeGeneratedMappingServiceImpl mappingImpl = new RuntimeGeneratedMappingServiceImpl();
+        mappingImpl.setPool(new ClassPool());
         SchemaService schemaService = (session.getService(SchemaService.class));
         ClassPool pool = new ClassPool();
         mappingImpl.setBinding(new TransformerGenerator(pool));
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend
deleted file mode 100644 (file)
index 84a0065..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.opendaylight.controller.sal.binding.impl.connect.dom
-
-import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
-import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import java.util.Collections
-import java.util.Map.Entry
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import java.util.AbstractMap.SimpleEntry
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-
-class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService {
-
-    var extension BindingMapping mapping = new BindingMapping;
-
-    @Property
-    BindingGeneratorImpl binding;
-
-    @Property
-    SchemaService schemaService;
-
-    override onGlobalContextUpdated(SchemaContext arg0) {
-        recreateBindingContext(arg0);
-    }
-
-    def recreateBindingContext(SchemaContext schemaContext) {
-        val newBinding = new BindingGeneratorImpl();
-        newBinding.generateTypes(schemaContext);
-        val newMapping = new BindingMapping();
-        for (entry : newBinding.moduleContexts.entrySet) {
-            val module = entry.key;
-            val context = entry.value;
-            
-            newMapping.updateBinding(schemaContext, context);
-        }
-        mapping = newMapping
-    }
-
-    override CompositeNode toDataDom(DataObject data) {
-        mapping.toCompositeNode(data);
-    }
-
-    override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
-        Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
-        val key = mapping.toDataDom(entry.key);
-        val data = mapping.toCompositeNode(entry.value);
-        return new SimpleEntry(key, data);
-    }
-
-    override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
-        InstanceIdentifier<? extends DataObject> path) {
-        return mapping.toDataDom(path);
-    }
-    
-    override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
-        return mapping.dataObjectFromDataDom(path,result);
-    }
-    
-    public def void start() {
-        schemaService.registerSchemaServiceListener(this);
-        recreateBindingContext(schemaService.globalContext);
-    }
-}
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
deleted file mode 100644 (file)
index c1efd11..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-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 87f31ac5c435820c5ddb5ec505e3dabbab94eba8..6478a03bbc025f8a7fa1f6ec937270a80d807797 100644 (file)
@@ -3,6 +3,7 @@ package org.opendaylight.controller.sal.binding.impl.util;
 
 
 import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
 
 import static com.google.common.base.Preconditions.*;
 
@@ -10,20 +11,35 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 
+import com.google.common.base.Optional;
+
 public class ClassLoaderUtils {
     
     public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
-        checkNotNull(cls);
-        checkNotNull(function);
+        return withClassLoaderAndLock(cls, Optional.<Lock>absent(), function);
+    }
+    
+    public static <V> V withClassLoaderAndLock(ClassLoader cls,Lock lock,Callable<V> function) throws Exception {
+        checkNotNull(lock,"Lock should not be null");
+        return withClassLoaderAndLock(cls, Optional.of(lock), function);
+    }
+    
+    public static <V> V withClassLoaderAndLock(ClassLoader cls,Optional<Lock> lock,Callable<V> function) throws Exception {
+        checkNotNull(cls, "Classloader should not be null");
+        checkNotNull(function,"Function should not be null");
+        if(lock.isPresent()) {
+            lock.get().lock();
+        }
         ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
         try {
             Thread.currentThread().setContextClassLoader(cls);
             V result = function.call();
-            Thread.currentThread().setContextClassLoader(oldCls);
             return result;
-        } catch (Exception e) {
+        }  finally {
             Thread.currentThread().setContextClassLoader(oldCls);
-            throw new Exception(e);
+            if(lock.isPresent()) {
+                lock.get().unlock();
+            }
         }
     }
 
index 27d985b2d26c0a260c8801fa7a5bbaea6f80021f..7d8a8f1fffa7703c2d1b567cbc372f694e4cdba0 100644 (file)
@@ -6,13 +6,14 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import javassist.ClassPool;
+
 import org.junit.Before;
 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.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.controller.sal.binding.test.connect.dom.MappingServiceTest;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
 import org.opendaylight.yangtools.yang.model.api.Module;
@@ -29,6 +30,12 @@ public  abstract class AbstractDataServiceTest {
     protected DataBrokerService biDataService;
     protected DataProviderService baDataService;
     
+    /**
+     * Workaround for JUNIT sharing classloaders
+     * 
+     */
+    protected static final ClassPool POOL = new ClassPool();
+    
     protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
     protected BindingIndependentMappingService mappingService;
     protected DataBrokerImpl baDataImpl;
@@ -56,6 +63,7 @@ public  abstract class AbstractDataServiceTest {
         biDataImpl.registerCommitHandler(treeRoot, dataStore);
         
         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+        mappingServiceImpl.setPool(POOL);
         mappingService = mappingServiceImpl;
         File pathname = new File("target/gen-classes-debug");
         //System.out.println("Generated classes are captured in " + pathname.getAbsolutePath());
@@ -69,15 +77,17 @@ public  abstract class AbstractDataServiceTest {
         connectorServiceImpl.start();
         
         String[] yangFiles= getModelFilenames();
-        mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+        if(yangFiles != null && yangFiles.length > 0) {
+            mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+        }
     }
 
 
     protected  String[] getModelFilenames() {
-        return getModelFilenamesImpl();
+        return getAllModelFilenames();
     }
     
-    public static String[] getModelFilenamesImpl() {
+    public static String[] getAllModelFilenames() {
         Predicate<String> predicate = new Predicate<String>() {
             @Override
             public boolean apply(String input) {
index 08eb409b3dbf9552a3152e2a88fb43ecb44f562c..4e7628fd06cc87254c2ce2df71a7b844070678d6 100644 (file)
@@ -1,22 +1,41 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
@@ -27,78 +46,130 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import static org.junit.Assert.*;
 
-/**
- * 
- * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=144
- * 
- * Cannot compile CoDec for org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
- * 
- * @author ttkacik
- *
- */
 public class DOMCodecBug01Test extends AbstractDataServiceTest {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
     private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
-    
     private static final long FLOW_ID = 1234;
     private static final String NODE_ID = "node:1";
 
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
-    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder().node(Nodes.class)
-            .node(Node.class, NODE_KEY).toInstance();
-    
-    
+
     private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
             NODE_ID);
-    
+
+    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .toInstance();
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .child(Node.class, NODE_KEY).toInstance();
+
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-                    .node(Nodes.QNAME) //
-                    .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
-                    .toInstance();
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
     private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
-    
+
     private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
 
     private static final Map<QName, Object> FLOW_KEY_BI = //
-            ImmutableMap.<QName,Object>of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_REF);
-
-
-    
+    ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI);
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-                    .node(Flows.QNAME) //
-                    .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
-                    .toInstance();
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Flows.QNAME) //
+            .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
+            .toInstance();
     private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
-            InstanceIdentifier.builder() //
-                .node(Flows.class) //
-                .node(Flow.class, FLOW_KEY) //
-                .toInstance();
+    InstanceIdentifier.builder() //
+            .node(Flows.class) //
+            .node(Flow.class, FLOW_KEY) //
+            .toInstance();
+
+
+
     /**
-     * 
+     *
+     * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=
+     *
+     * Cannot compile CoDec for
+     * org.opendaylight.yang.gen.v1.urn.opendaylight.flow
+     * .config.rev130819.flows.Flow
+     *
      * When invoking following code in the consumer, user got an
      * IllegalStateException during creation of mapping between Java DTOs and
      * data-dom.
-     * 
+     *
      * Exception was compilation error which was caused by incorect generation
      * of code.
-     * 
-     * 
+     *
+     * Reported by Depthi V V
+     *
      */
     @Test
     public void testIndirectGeneration() throws Exception {
 
+        ExecutorService basePool = Executors.newFixedThreadPool(2);
+        ListeningExecutorService listenablePool = MoreExecutors.listeningDecorator(basePool);
+
+        createFlow();
+
+        Object lock = new Object();
+        CreateFlowTask task1 = new CreateFlowTask(lock);
+        CreateFlowTask task2 = new CreateFlowTask(lock);
+        CreateFlowTask task3 = new CreateFlowTask(lock);
+
+        ListenableFuture<Void> task1Future = listenablePool.submit(task1);
+        ListenableFuture<Void> task2Future = listenablePool.submit(task2);
+        ListenableFuture<Void> task3Future = listenablePool.submit(task3);
+
+
+        ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
+
+        Thread.sleep(500);
+        //lock.notifyAll();
+        compositeFuture.get();
+
+        verifyDataAreStoredProperly();
+
+        DataModificationTransaction modification2 = baDataService.beginTransaction();
+        modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
+
+        DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
+        assertNotNull(originalData);
+        RpcResult<TransactionStatus> ret2 = modification2.commit().get();
+
+        assertNotNull(ret2);
+        assertEquals(TransactionStatus.COMMITED, ret2.getResult());
+
+        // Data are not in the store.
+        assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
+
+    }
+
+    private void createFlow() throws Exception {
+
         DataModificationTransaction modification = baDataService.beginTransaction();
 
-       FlowBuilder flow = new FlowBuilder();
+        FlowBuilder flow = new FlowBuilder();
         MatchBuilder match = new MatchBuilder();
         VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
@@ -110,35 +181,58 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         flow.setMatch(match.build());
         flow.setNode(NODE_REF);
 
+
+        InstructionsBuilder instructions = new InstructionsBuilder();
+        InstructionBuilder instruction = new InstructionBuilder();
+        ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
+        List<Action> actionList = new ArrayList<>();
+        PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
+        popMplsAction.setEthernetType(34);
+        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build());
+
+        applyActions.setAction(actionList );
+
+
+        instruction.setInstruction(applyActions.build());
+
+
+        List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
+        instructions.setInstruction(instructionList );
+
+        flow.setInstructions(instructions.build());
         modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
         RpcResult<TransactionStatus> ret = modification.commit().get();
         assertNotNull(ret);
         assertEquals(TransactionStatus.COMMITED, ret.getResult());
-        
-        verifyDataAreStoredProperly();
-        
-        
-        DataModificationTransaction modification2 = baDataService.beginTransaction();
-        modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
-        
-        DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
-        assertNotNull(originalData);
-        RpcResult<TransactionStatus> ret2 = modification2.commit().get();
-        
-        assertNotNull(ret2);
-        assertEquals(TransactionStatus.COMMITED, ret2.getResult());
-        
-        
-        // Data are not in the store.
-        assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
-        
-        
+    }
+
+    private class CreateFlowTask implements Callable<Void> {
+
+        final Object startSyncObject;
+
+        public CreateFlowTask(Object startSync) {
+            startSyncObject = startSync;
+        }
+
+        @Override
+        public Void call() {
+            try {
+                //startSyncObject.wait();
+                //Thread.sleep(500);
+                createFlow();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            return null;
+        }
     }
 
     private void verifyDataAreStoredProperly() {
         CompositeNode biFlow = biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI);
         assertNotNull(biFlow);
-        CompositeNode biMatch = biFlow.getFirstCompositeByName(QName.create(Flow.QNAME,Match.QNAME.getLocalName()));
+        CompositeNode biMatch = biFlow.getFirstCompositeByName(QName.create(Flow.QNAME, Match.QNAME.getLocalName()));
         assertNotNull(biMatch);
     }
+
+
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java
new file mode 100644 (file)
index 0000000..773bab8
--- /dev/null
@@ -0,0 +1,121 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static org.junit.Assert.*;
+
+public class DOMCodecBug02Test extends AbstractDataServiceTest {
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
+    private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
+
+    private static final String FLOW_ID = "foo";
+    private static final String NODE_ID = "node:1";
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+    private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+            NODE_ID);
+
+    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .toInstance();
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .child(Node.class, NODE_KEY).toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
+    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+
+    @Override
+    protected String[] getModelFilenames() {
+        return null;
+    }
+
+    /**
+     * 
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testSchemaContextNotAvailable() throws Exception {
+
+        ExecutorService testExecutor = Executors.newFixedThreadPool(1);
+        
+        Future<Future<RpcResult<TransactionStatus>>> future = testExecutor.submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
+            @Override
+            public Future<RpcResult<TransactionStatus>> call() throws Exception {
+                NodesBuilder nodesBuilder = new NodesBuilder();
+                nodesBuilder.setNode(Collections.<Node> emptyList());
+                DataModificationTransaction transaction = baDataService.beginTransaction();
+                transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
+                return transaction.commit();
+            }
+        });
+        mappingServiceImpl.onGlobalContextUpdated(getContext(getAllModelFilenames()));
+        
+        RpcResult<TransactionStatus> result = future.get().get();
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        
+        
+        Nodes nodes = checkForNodes();
+        assertNotNull(nodes);
+
+    }
+
+    private Nodes checkForNodes() {
+        return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java
new file mode 100644 (file)
index 0000000..ae54591
--- /dev/null
@@ -0,0 +1,156 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static org.junit.Assert.*;
+
+public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener {
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final String NODE_ID = "openflow:1";
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+    private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+            NODE_ID);
+
+    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .toInstance();
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+            .node(Nodes.class) //
+            .child(Node.class, NODE_KEY).toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
+    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+    private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+
+    
+    
+    /**
+     * Test for Bug 148
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testAugmentSerialization() throws Exception {
+
+        
+        baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
+        
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setId(new NodeId(NODE_ID));
+        nodeBuilder.setKey(NODE_KEY);
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        
+        
+        FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder();
+        fnub.setHardware("Hardware Foo");
+        fnub.setManufacturer("Manufacturer Foo");
+        fnub.setSerialNumber("Serial Foo");
+        fnub.setDescription("Description Foo");
+        fnub.setSoftware("JUnit emulated");
+        FlowCapableNode fnu = fnub.build();
+        nodeBuilder.addAugmentation(FlowCapableNode.class, fnu);
+        Node original = nodeBuilder.build();
+        transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
+        
+        RpcResult<TransactionStatus> result = transaction.commit().get();
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        
+        assertNotNull(receivedChangeEvent);
+        
+        verifyNodes((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(),original);
+        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+        Nodes nodes = checkForNodes();
+        verifyNodes(nodes,original);
+        
+        
+    }
+
+    private void verifyNodes(Nodes nodes,Node original) {
+        assertNotNull(nodes);
+        assertNotNull(nodes.getNode());
+        assertEquals(1, nodes.getNode().size());
+        Node readedNode = nodes.getNode().get(0);
+        assertEquals(original.getId(), readedNode.getId());
+        assertEquals(original.getKey(), readedNode.getKey());
+        
+        FlowCapableNode fnu = original.getAugmentation(FlowCapableNode.class);
+        FlowCapableNode readedAugment = readedNode.getAugmentation(FlowCapableNode.class);
+        assertNotNull(fnu);
+        assertEquals(fnu.getDescription(), readedAugment.getDescription());
+        assertEquals(fnu.getSerialNumber(), readedAugment.getSerialNumber());
+        
+    }
+
+    private void assertBindingIndependentVersion(
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+        CompositeNode node = biDataService.readOperationalData(nodeId);
+        assertNotNull(node);
+    }
+
+    private Nodes checkForNodes() {
+        return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+    }
+    
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        receivedChangeEvent = change;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java
deleted file mode 100644 (file)
index e26273e..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.opendaylight.controller.sal.binding.test.connect.dom;
-
-import static org.junit.Assert.*;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.junit.Before;
-import org.junit.Test;
-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.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-public class MappingServiceTest {
-
-    private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes");
-    private static final QName NODE = QName.create(NODES,"node");
-    private static final QName ID = QName.create(NODES,"id");
-    
-    BindingIndependentMappingService service;
-    private MappingServiceImpl impl;
-
-    @Before
-    public void setUp() {
-        impl = new MappingServiceImpl();
-        service = impl;
-    }
-
-    @Test
-    public void baDataToBiData() throws Exception {
-
-        String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
-
-        SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
-
-        impl.onGlobalContextUpdated(ctx);
-
-        NodesBuilder nodes = new NodesBuilder();
-
-        List<Node> nodeList = new ArrayList<>();
-        nodeList.add(createChildNode("foo"));
-        nodeList.add(createChildNode("bar"));
-
-        nodes.setNode(nodeList);
-        Nodes nodesTO = nodes.build();
-        CompositeNode xmlNodes = service.toDataDom(nodesTO);
-        assertNotNull(xmlNodes);
-        List<CompositeNode> invNodes = xmlNodes.getCompositesByName(NODE);
-        assertNotNull(invNodes);
-        assertEquals(2, invNodes.size());
-    }
-
-    @Test
-    public void instanceIdentifierTest() throws Exception {
-
-        String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
-        SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
-        impl.onGlobalContextUpdated(ctx);
-
-        NodeKey nodeKey = new NodeKey(new NodeId("foo"));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance();
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path);
-        assertNotNull(result);
-        assertEquals(2, result.getPath().size());
-    }
-
-    private Node createChildNode(String id) {
-        NodeBuilder node = new NodeBuilder();
-        NodeId nodeId = new NodeId(id);
-
-        node.setId(nodeId);
-        node.setKey(new NodeKey(nodeId));
-
-        FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder();
-        aug.setManufacturer(id);
-        node.addAugmentation(FlowCapableNode.class, aug.build());
-
-        return node.build();
-    }
-
-}
index b878071183e14937a63a1ce8981bcfaa5785566d..74c4e0a148640a2278deee8a87bf67c4c27eb334 100644 (file)
@@ -27,25 +27,37 @@ import java.util.concurrent.Future
 import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
 import org.opendaylight.yangtools.concepts.Path
 import org.slf4j.LoggerFactory
-
-abstract class AbstractDataBroker<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> implements 
-DataModificationTransactionFactory<P, D>, //
+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
+import com.google.common.collect.ImmutableList
+
+abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
 DataReader<P, D>, //
 DataChangePublisher<P, D, DCL>, //
-DataProvisionService<P,D> {
+DataProvisionService<P, D> {
 
     @Property
     var ExecutorService executor;
 
     @Property
-    var AbstractDataReadRouter<P,D> dataReadRouter;
-
-    Multimap<P, DataChangeListenerRegistration<P,D,DCL>> listeners = HashMultimap.create();
-    Multimap<P, DataCommitHandlerRegistration<P,D>> commitHandlers = HashMultimap.create();
+    var AbstractDataReadRouter<P, D> dataReadRouter;
 
+    Multimap<P, DataChangeListenerRegistration<P, D, DCL>> listeners = HashMultimap.create();
+    Multimap<P, DataCommitHandlerRegistration<P, D>> commitHandlers = HashMultimap.create();
 
     public new() {
-        
+    }
+
+    protected def /*Iterator<Entry<Collection<DataChangeListenerRegistration<P,D,DCL>>,D>>*/ affectedCommitHandlers(
+        HashSet<P> paths) {
+        return FluentIterable.from(commitHandlers.asMap.entrySet)
+            .filter[key.isAffectedBy(paths)] //
+            .transformAndConcat [value] //
+            .transform[instance].toList()
     }
 
     override final readConfigurationData(P path) {
@@ -56,11 +68,10 @@ DataProvisionService<P,D> {
         return dataReadRouter.readOperationalData(path);
     }
 
-    override final registerCommitHandler(P path,
-        DataCommitHandler<P, D> commitHandler) {
-            val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
-            commitHandlers.put(path,registration)
-            return registration;
+    override final registerCommitHandler(P path, DataCommitHandler<P, D> commitHandler) {
+        val registration = new DataCommitHandlerRegistration(path, commitHandler, this);
+        commitHandlers.put(path, registration)
+        return registration;
     }
 
     override final def registerDataChangeListener(P path, DCL listener) {
@@ -69,27 +80,49 @@ DataProvisionService<P,D> {
         return reg;
     }
 
-     final def registerDataReader(P path,DataReader<P,D> reader) {
-        
-        val confReg = dataReadRouter.registerConfigurationReader(path,reader);
-        val dataReg = dataReadRouter.registerOperationalReader(path,reader);
-        
-        return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
+    final def registerDataReader(P path, DataReader<P, D> reader) {
+
+        val confReg = dataReadRouter.registerConfigurationReader(path, reader);
+        val dataReg = dataReadRouter.registerOperationalReader(path, reader);
+
+        return new CompositeObjectRegistration(reader, Arrays.asList(confReg, dataReg));
     }
 
-    protected  final def removeListener(DataChangeListenerRegistration<P,D,DCL> registration) {
+    protected final def removeListener(DataChangeListenerRegistration<P, D, DCL> registration) {
         listeners.remove(registration.path, registration);
     }
 
-    protected  final def removeCommitHandler(DataCommitHandlerRegistration<P,D> registration) {
+    protected final def removeCommitHandler(DataCommitHandlerRegistration<P, D> registration) {
         commitHandlers.remove(registration.path, registration);
     }
-    
-    protected  final def getActiveCommitHandlers() {
-        return commitHandlers.entries.map[ value.instance].toSet
+
+    protected final def getActiveCommitHandlers() {
+        return commitHandlers.entries;
     }
 
-    package final def Future<RpcResult<TransactionStatus>>  commit(AbstractDataTransaction<P,D> transaction) {
+    protected def /*Iterator<Entry<Collection<DataChangeListenerRegistration<P,D,DCL>>,D>>*/ affectedListenersWithInitialState(
+        HashSet<P> paths) {
+        return FluentIterable.from(listeners.asMap.entrySet).filter[key.isAffectedBy(paths)].transform [
+            val operationalState = readOperationalData(key)
+            val configurationState = readConfigurationData(key)
+            return new ListenerStateCapture(key, value, operationalState, configurationState)
+        ].toList()
+    }
+
+    protected def boolean isAffectedBy(P key, Set<P> paths) {
+        if (paths.contains(key)) {
+            return true;
+        }
+        for (path : paths) {
+            if (key.contains(path)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    package final def Future<RpcResult<TransactionStatus>> commit(AbstractDataTransaction<P, D> transaction) {
         checkNotNull(transaction);
         transaction.changeStatus(TransactionStatus.SUBMITED);
         val task = new TwoPhaseCommit(transaction, this);
@@ -98,14 +131,30 @@ DataProvisionService<P,D> {
 
 }
 
-package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+@Data
+package class ListenerStateCapture<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> {
 
-    AbstractDataBroker<P,D,DCL> dataBroker;
+    @Property
+    P path;
+
+    @Property
+    Collection<DataChangeListenerRegistration<P, D, DCL>> listeners;
+
+    @Property
+    D initialOperationalState;
+
+    @Property
+    D initialConfigurationState;
+}
+
+package class DataChangeListenerRegistration<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+
+    AbstractDataBroker<P, D, DCL> dataBroker;
 
     @Property
     val P path;
 
-    new(P path, DCL instance, AbstractDataBroker<P,D,DCL> broker) {
+    new(P path, DCL instance, AbstractDataBroker<P, D, DCL> broker) {
         super(instance)
         dataBroker = broker;
         _path = path;
@@ -118,16 +167,14 @@ package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends Dat
 
 }
 
-package class DataCommitHandlerRegistration<P extends Path<P>,D>
-extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+package class DataCommitHandlerRegistration<P extends Path<P>, D> extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
 
-    AbstractDataBroker<P,D,?> dataBroker;
+    AbstractDataBroker<P, D, ?> dataBroker;
 
     @Property
     val P path;
 
-    new(P path, DataCommitHandler<P, D> instance,
-        AbstractDataBroker<P,D,?> broker) {
+    new(P path, DataCommitHandler<P, D> instance, AbstractDataBroker<P, D, ?> broker) {
         super(instance)
         dataBroker = broker;
         _path = path;
@@ -140,74 +187,105 @@ extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
 
 }
 
-package class TwoPhaseCommit<P extends Path<P>,D> implements Callable<RpcResult<TransactionStatus>> {
-    
+package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> implements Callable<RpcResult<TransactionStatus>> {
+
     private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
 
-    val AbstractDataTransaction<P,D> transaction;
-    val AbstractDataBroker<P,D,?> dataBroker;
+    val AbstractDataTransaction<P, D> transaction;
+    val AbstractDataBroker<P, D, DCL> dataBroker;
 
-    new(AbstractDataTransaction<P,D> transaction, AbstractDataBroker<P,D,?> broker) {
+    new(AbstractDataTransaction<P, D> transaction, AbstractDataBroker<P, D, DCL> broker) {
         this.transaction = transaction;
         this.dataBroker = broker;
     }
 
     override call() throws Exception {
 
-        val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.activeCommitHandlers;
+        // get affected paths
+        val affectedPaths = new HashSet<P>();
+
+        affectedPaths.addAll(transaction.createdConfigurationData.keySet);
+        affectedPaths.addAll(transaction.updatedConfigurationData.keySet);
+        affectedPaths.addAll(transaction.removedConfigurationData);
+
+        affectedPaths.addAll(transaction.createdOperationalData.keySet);
+        affectedPaths.addAll(transaction.updatedOperationalData.keySet);
+        affectedPaths.addAll(transaction.removedOperationalData);
+
+        val listeners = dataBroker.affectedListenersWithInitialState(affectedPaths);
 
         // requesting commits
+        val Iterable<DataCommitHandler<P, D>> commitHandlers =   dataBroker.affectedCommitHandlers(affectedPaths);
         val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
         try {
             for (handler : commitHandlers) {
                 handlerTransactions.add(handler.requestCommit(transaction));
             }
         } catch (Exception e) {
-            log.error("Request Commit failded",e);
-            return rollback(handlerTransactions,e);
+            log.error("Request Commit failded", e);
+            return rollback(handlerTransactions, e);
         }
         val List<RpcResult<Void>> results = new ArrayList();
         try {
             for (subtransaction : handlerTransactions) {
                 results.add(subtransaction.finish());
             }
+            listeners.publishDataChangeEvent();
         } catch (Exception e) {
-            log.error("Finish Commit failed",e);
-            return rollback(handlerTransactions,e);
+            log.error("Finish Commit failed", e);
+            return rollback(handlerTransactions, e);
         }
 
+        
         return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+
+    }
+    
+    def void publishDataChangeEvent(ImmutableList<ListenerStateCapture<P, D,DCL>> listeners) {
+        for(listenerSet : listeners) {
+            val updatedConfiguration = dataBroker.readConfigurationData(listenerSet.path);
+            val updatedOperational = dataBroker.readOperationalData(listenerSet.path);
+            
+            val changeEvent = new DataChangeEventImpl(transaction,listenerSet.initialConfigurationState,listenerSet.initialOperationalState,updatedOperational,updatedConfiguration);
+            for(listener : listenerSet.listeners) {
+                try {
+                    listener.instance.onDataChanged(changeEvent);
+                    
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
     }
 
-    def rollback(List<DataCommitTransaction<P, D>> transactions,Exception e) {
+    def rollback(List<DataCommitTransaction<P, D>> transactions, Exception e) {
         for (transaction : transactions) {
             transaction.rollback()
         }
+
         // FIXME return encountered error.
         return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
     }
 }
-
 public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
 
     @Property
     private val Object identifier;
 
-    
     var TransactionStatus status;
-    
-    
+
     var AbstractDataBroker<P, D, ?> broker;
 
-    protected new (AbstractDataBroker<P,D,?> dataBroker) {
+    protected new(AbstractDataBroker<P, D, ?> dataBroker) {
         super(dataBroker);
         _identifier = new Object();
         broker = dataBroker;
         status = TransactionStatus.NEW;
-        //listeners = new ListenerRegistry<>();
+
+    //listeners = new ListenerRegistry<>();
     }
 
-    override  commit() {
+    override commit() {
         return broker.commit(this);
     }
 
@@ -230,7 +308,7 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D> extends Abst
             return false;
         if (getClass() != obj.getClass())
             return false;
-        val other = (obj as AbstractDataTransaction<P,D>) ;
+        val other = (obj as AbstractDataTransaction<P,D>);
         if (broker == null) {
             if (other.broker != null)
                 return false;
@@ -248,12 +326,11 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D> extends Abst
         return status;
     }
 
-    
     protected abstract def void onStatusChange(TransactionStatus status);
-    
+
     public def changeStatus(TransactionStatus status) {
         this.status = status;
         onStatusChange(status);
     }
-    
+
 }
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java
new file mode 100644 (file)
index 0000000..4eb9586
--- /dev/null
@@ -0,0 +1,73 @@
+package org.opendaylight.controller.md.sal.common.impl.service;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChange;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+
+public class DataChangeEventImpl<P, D> implements DataChangeEvent<P, D> {
+
+    private final DataChange<P, D> dataChange;
+
+    private final D originalConfigurationSubtree;
+    private final D originalOperationalSubtree;
+    private final D updatedOperationalSubtree;
+    private final D updatedConfigurationSubtree;
+
+    
+    
+    
+    public DataChangeEventImpl(DataChange<P, D> dataChange, D originalConfigurationSubtree,
+            D originalOperationalSubtree, D updatedOperationalSubtree, D updatedConfigurationSubtree) {
+        super();
+        this.dataChange = dataChange;
+        this.originalConfigurationSubtree = originalConfigurationSubtree;
+        this.originalOperationalSubtree = originalOperationalSubtree;
+        this.updatedOperationalSubtree = updatedOperationalSubtree;
+        this.updatedConfigurationSubtree = updatedConfigurationSubtree;
+    }
+
+    @Override
+    public D getUpdatedOperationalSubtree() {
+        return updatedOperationalSubtree;
+    }
+
+    @Override
+    public D getUpdatedConfigurationSubtree() {
+        return updatedConfigurationSubtree;
+    }
+
+    public Map<P, D> getCreatedOperationalData() {
+        return dataChange.getCreatedOperationalData();
+    }
+
+    public Map<P, D> getCreatedConfigurationData() {
+        return dataChange.getCreatedConfigurationData();
+    }
+
+    public Map<P, D> getUpdatedOperationalData() {
+        return dataChange.getUpdatedOperationalData();
+    }
+
+    public Map<P, D> getUpdatedConfigurationData() {
+        return dataChange.getUpdatedConfigurationData();
+    }
+
+    public Set<P> getRemovedConfigurationData() {
+        return dataChange.getRemovedConfigurationData();
+    }
+
+    public Set<P> getRemovedOperationalData() {
+        return dataChange.getRemovedOperationalData();
+    }
+
+    public Map<P, D> getOriginalConfigurationData() {
+        return dataChange.getOriginalConfigurationData();
+    }
+
+    public Map<P, D> getOriginalOperationalData() {
+        return dataChange.getOriginalOperationalData();
+    }
+
+}
index 3115994e01575a57661db4bbc73bc81927e9713d..a0acaf156facb47a74f9e672f1514277f78fc4a4 100644 (file)
@@ -17,17 +17,17 @@ import com.google.gson.JsonPrimitive;
 
 class JsonReader {
 
-    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedJsonFormatException {
+    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedFormatException {
         JsonParser parser = new JsonParser();
         
         JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
         if (!rootElement.isJsonObject()) {
-            throw new UnsupportedJsonFormatException("Root element of Json has to be Object");
+            throw new UnsupportedFormatException("Root element of Json has to be Object");
         }
         
         Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
         if (entrySetsOfRootJsonObject.size() != 1) {
-            throw new UnsupportedJsonFormatException("Json Object should contain one element");
+            throw new UnsupportedFormatException("Json Object should contain one element");
         } else {
             Entry<String, JsonElement> childEntry = Lists.newArrayList(entrySetsOfRootJsonObject).get(0);
             String firstElementName = childEntry.getKey();
@@ -41,10 +41,10 @@ class JsonReader {
                     if (firstElementInArray.isJsonObject()) {
                         return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
                     }
-                    throw new UnsupportedJsonFormatException("Array as the first element in Json Object can have only Object element");
+                    throw new UnsupportedFormatException("Array as the first element in Json Object can have only Object element");
                 }
             }
-            throw new UnsupportedJsonFormatException("First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
+            throw new UnsupportedFormatException("First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
         }
     }
     
index daaedd92b8d6c85f05f26365b90f6bbe68f7d5d6..dea4a73cd17d23f53f7c88d9b2ace669b285a2a6 100644 (file)
@@ -35,8 +35,8 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
         JsonReader jsonReader = new JsonReader();
         try {
             return jsonReader.read(entityStream);
-        } catch (UnsupportedJsonFormatException e) {
-            throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+        } catch (UnsupportedFormatException e) {
+            throw new WebApplicationException(e,Response.status(Response.Status.BAD_REQUEST)
                     .entity(e.getMessage()).build());
         }
     }
index 6dc74840810a195d7e8a1bd8771a947530ce307a..bede249c943a08bc40bb97ccc39aebac9d2abe58 100644 (file)
@@ -24,6 +24,8 @@ public class RestconfApplication extends Application {
         singletons.add(restconfImpl);
         singletons.add(XmlToCompositeNodeProvider.INSTANCE);
         singletons.add(StructuredDataToXmlProvider.INSTANCE);
+        singletons.add(JsonToCompositeNodeProvider.INSTANCE);
+        singletons.add(StructuredDataToJsonProvider.INSTANCE);
         return singletons;
     }
 
index 4a851a3f6ca531f6042b9d20df7f4d9ba3cd3517..90e6d2affc5cde925d4adc941b24d42005aad117 100644 (file)
@@ -24,7 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import com.google.gson.stream.JsonWriter;
 
 @Provider
-@Produces({ API + RestconfService.JSON })
+@Produces({API+RestconfService.JSON})
 public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
     
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java
new file mode 100644 (file)
index 0000000..615f209
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+public class UnsupportedFormatException extends Exception {
+
+    private static final long serialVersionUID = -1741388894406313402L;
+
+    public UnsupportedFormatException() {
+        super();
+    }
+
+    public UnsupportedFormatException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UnsupportedFormatException(String message) {
+        super(message);
+    }
+
+    public UnsupportedFormatException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java
deleted file mode 100644 (file)
index dccf29b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.opendaylight.controller.sal.rest.impl;
-
-public class UnsupportedJsonFormatException extends Exception {
-
-    private static final long serialVersionUID = -1741388894406313402L;
-
-    public UnsupportedJsonFormatException() {
-        super();
-    }
-
-    public UnsupportedJsonFormatException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public UnsupportedJsonFormatException(String message) {
-        super(message);
-    }
-
-    public UnsupportedJsonFormatException(Throwable cause) {
-        super(cause);
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
new file mode 100644 (file)
index 0000000..9f31eb4
--- /dev/null
@@ -0,0 +1,157 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Stack;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+
+public class XmlReader {
+    
+    private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+    private XMLEventReader eventReader;
+
+    public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException {
+        eventReader = xmlInputFactory.createXMLEventReader(entityStream);
+        
+        if (eventReader.hasNext()) {
+            XMLEvent element = eventReader.peek();
+            if (element.isStartDocument()) {
+                eventReader.nextEvent();
+            }
+        }
+
+        if (eventReader.hasNext() && !isCompositeNodeEvent(eventReader.peek())) {
+            throw new UnsupportedFormatException("Root element of XML has to be composite element.");
+        }
+        
+        final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
+        CompositeNodeWrapper root = null;
+        NodeWrapper<?> element = null;
+        while (eventReader.hasNext()) {
+            final XMLEvent event = eventReader.nextEvent();
+
+            if (event.isStartElement()) {
+                final StartElement startElement = event.asStartElement();
+                CompositeNodeWrapper compParentNode = null;
+                if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
+                    compParentNode = (CompositeNodeWrapper) processingQueue.peek();
+                }
+                NodeWrapper<?> newNode = null;
+                if (isCompositeNodeEvent(event)) {
+                    if (root == null) {
+                        root = resolveCompositeNodeFromStartElement(startElement);
+                        newNode = root;
+                    } else {
+                        newNode = resolveCompositeNodeFromStartElement(startElement);
+                    }
+                } else if (isSimpleNodeEvent(event)) {
+                    if (root == null) {
+                        throw new UnsupportedFormatException("Root element of XML has to be composite element.");
+                    }
+                    newNode = resolveSimpleNodeFromStartElement(startElement);
+                }
+
+                if (newNode != null) {
+                    processingQueue.push(newNode);
+                    if (compParentNode != null) {
+                        compParentNode.addValue(newNode);
+                    }
+                }
+            } else if (event.isEndElement()) {
+                element = processingQueue.pop();
+            }
+        }
+        
+        if (!root.getLocalName().equals(element.getLocalName())) {
+            throw new UnsupportedFormatException("XML should contain only one root element");
+        }
+        
+        return root;
+    }
+    
+    private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            if (eventReader.hasNext()) {
+                final XMLEvent innerEvent;
+                innerEvent = eventReader.peek();
+                if (innerEvent.isCharacters()) {
+                    final Characters chars = innerEvent.asCharacters();
+                    if (!chars.isWhiteSpace()) {
+                        return true;
+                    }
+                } else if (innerEvent.isEndElement()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            if (eventReader.hasNext()) {
+                XMLEvent innerEvent;
+                innerEvent = eventReader.peek();
+                if (innerEvent.isCharacters()) {
+                    Characters chars = innerEvent.asCharacters();
+                    if (chars.isWhiteSpace()) {
+                        eventReader.nextEvent();
+                        innerEvent = eventReader.peek();
+                    }
+                }
+                if (innerEvent.isStartElement()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement) throws XMLStreamException {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        String data = null;
+
+        if (eventReader.hasNext()) {
+            final XMLEvent innerEvent = eventReader.peek();
+            if (innerEvent.isCharacters()) {
+                final Characters chars = innerEvent.asCharacters();
+                if (!chars.isWhiteSpace()) {
+                    data = innerEvent.asCharacters().getData();
+                }
+            } else if (innerEvent.isEndElement()) {
+                data = "";
+            }
+        }
+        
+        return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
+    }
+    
+    private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        return new CompositeNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
+    }
+    
+    private String getLocalNameFrom(StartElement startElement) {
+        return startElement.getName().getLocalPart();
+    }
+    
+    private URI getNamespaceFrom(StartElement startElement) {
+        String namespaceURI = startElement.getName().getNamespaceURI();
+        return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
+    }
+    
+}
index 09733f5e907faa533167be5211b39cf2839b6345..19720107d3b2e12a63e10cedec8ec173b7ea52e8 100644 (file)
@@ -18,18 +18,11 @@ import javax.xml.stream.XMLStreamException;
 
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @Provider
-@Consumes({API+RestconfService.XML})
+@Consumes({ API + RestconfService.XML })
 public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
-    
-    private final static Logger logger = LoggerFactory.getLogger(XmlToCompositeNodeProvider.class);
 
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
@@ -40,18 +33,12 @@ public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNod
     public CompositeNode readFrom(Class<CompositeNode> type, Type genericType, Annotation[] annotations,
             MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
             throws IOException, WebApplicationException {
+        XmlReader xmlReader = new XmlReader();
         try {
-            Node<?> node = XmlTreeBuilder.buildDataTree(entityStream);
-            if (node instanceof SimpleNode) {
-                logger.info("Node is SimpleNode");
-                throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
-                        .entity("XML should start with XML element that contains 1..N XML child elements.").build());
-            }
-            return (CompositeNode) node;
-        } catch (XMLStreamException e) {
-            logger.info("Error during translation of InputStream to Node\n" + e.getMessage());
-            throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
-                    .entity(e.getMessage()).build());
+            return xmlReader.read(entityStream);
+        } catch (XMLStreamException | UnsupportedFormatException e) {
+            throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
+                    .build());
         }
     }
 
index ea3a4fbcfcbae90e848c39e505008dd701613b26..a41a48287df87f887dd37c12b0fd88f4539f7597 100644 (file)
@@ -113,7 +113,7 @@ class RestconfImpl implements RestconfService {
             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
             for (child : children) {
                 addNamespaceToNodeFromSchemaRecursively(child,
-                    (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName === child.localName])
+                    (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName.equals(child.localName)])
             }
         }
     }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java
new file mode 100644 (file)
index 0000000..a32a347
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import java.util.concurrent.*;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class DummyFuture implements Future<RpcResult<TransactionStatus>> {
+
+    @Override
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        return false;
+    }
+
+    @Override
+    public boolean isCancelled() {
+        return false;
+    }
+
+    @Override
+    public boolean isDone() {
+        return false;
+    }
+
+    @Override
+    public RpcResult<TransactionStatus> get() throws InterruptedException, ExecutionException {
+        return null;
+    }
+
+    @Override
+    public RpcResult<TransactionStatus> get(long timeout, TimeUnit unit) throws InterruptedException,
+            ExecutionException, TimeoutException {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromJsonToCompositeNode.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromJsonToCompositeNode.java
new file mode 100644 (file)
index 0000000..dbbb4a6
--- /dev/null
@@ -0,0 +1,259 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.*;
+import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.*;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.slf4j.*;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+import com.google.gson.JsonSyntaxException;
+
+public class FromJsonToCompositeNode {
+
+    private static Logger LOG = LoggerFactory.getLogger(FromJsonToCompositeNode.class);
+
+    @Test
+    public void simpleListTest() {
+        simpleTest("/json-to-composite-node/simple-list.json", "/json-to-composite-node/simple-list-yang", "lst",
+                "simple:data:types");
+    }
+
+    @Test
+    public void simpleContainerTest() {
+        simpleTest("/json-to-composite-node/simple-container.json", "/json-to-composite-node/simple-container-yang",
+                "cont", "simple:data:types");
+    }
+
+    /**
+     * List contains 4 items and in every item are other elements. It is
+     * supposed that there should be: lf11, lflst11, cont11, lst11
+     */
+    @Test
+    public void multipleItemsInListTest() {
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/multiple-items-in-list.json",
+                true);
+        assertNotNull(compositeNode);
+
+        assertEquals("lst", compositeNode.getNodeType().getLocalName());
+
+        verityMultipleItemsInList(compositeNode);
+    }
+
+    @Test
+    public void incorrectTopLevelElementsTest() {
+        Throwable cause1 = null;
+        try {
+            compositeContainerFromJson("/json-to-composite-node/wrong-top-level1.json", true);
+        } catch (WebApplicationException e) {
+            cause1 = e;
+        }
+
+        assertNotNull(cause1);
+        assertTrue(cause1
+                .getCause()
+                .getMessage()
+                .contains(
+                        "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+
+        Throwable cause2 = null;
+        try {
+            compositeContainerFromJson("/json-to-composite-node/wrong-top-level2.json", true);
+        } catch (WebApplicationException e) {
+            cause2 = e;
+        }
+        assertNotNull(cause2);
+        assertTrue(cause2.getCause().getMessage().contains("Json Object should contain one element"));
+
+        Throwable cause3 = null;
+        try {
+            compositeContainerFromJson("/json-to-composite-node/wrong-top-level3.json", true);
+        } catch (WebApplicationException e) {
+            cause3 = e;
+        }
+        assertNotNull(cause3);
+        assertTrue(cause3
+                .getCause()
+                .getMessage()
+                .contains(
+                        "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+
+    }
+
+    /**
+     * if leaf list with no data is in json then no corresponding data is
+     * created in composite node. if leaf with no data then exception is raised
+     */
+    @Test
+    public void emptyDataReadTest() {
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/empty-data.json", true);
+
+        assertNotNull(compositeNode);
+
+        assertEquals("cont", compositeNode.getNodeType().getLocalName());
+        assertTrue(compositeNode instanceof CompositeNode);
+        List<Node<?>> children = ((CompositeNode) compositeNode).getChildren();
+        assertEquals(1, children.size());
+        assertEquals("lflst2", children.get(0).getNodeType().getLocalName());
+        assertEquals("45", children.get(0).getValue());
+
+        String reason = null;
+        try {
+            compositeContainerFromJson("/json-to-composite-node/empty-data1.json", true);
+        } catch (JsonSyntaxException e) {
+            reason = e.getMessage();
+        }
+
+        assertTrue(reason.contains("Expected value at line"));
+
+    }
+
+    private void simpleTest(String jsonPath, String yangPath, String topLevelElementName, String namespace) {
+        CompositeNode compositeNode = compositeContainerFromJson(jsonPath);
+        assertNotNull(compositeNode);
+
+        DataSchemaNode dataSchemaNode = null;
+        try {
+            dataSchemaNode = TestUtils.obtainSchemaFromYang(yangPath);
+        } catch (FileNotFoundException e) {
+            LOG.error(e.getMessage());
+            assertTrue(false);
+        }
+        assertNotNull(dataSchemaNode);
+
+        TestUtils.supplementNamespace(dataSchemaNode, compositeNode);
+
+        assertTrue(compositeNode instanceof CompositeNodeWrapper);
+        CompositeNode compNode = ((CompositeNodeWrapper) compositeNode).unwrap(null);
+
+        assertEquals(topLevelElementName, compNode.getNodeType().getLocalName());
+        verifyCompositeNode(compNode, namespace);
+    }
+
+    private void verityMultipleItemsInList(CompositeNode compositeNode) {
+        List<Node<?>> childrenNodes = compositeNode.getChildren();
+        assertEquals(4, childrenNodes.size());
+        boolean lf11Found = false;
+        boolean cont11Found = false;
+        boolean lst11Found = false;
+        for (Node<?> lst1Item : childrenNodes) {
+            assertEquals("lst1", lst1Item.getNodeType().getLocalName());
+            assertTrue(lst1Item instanceof CompositeNode);
+
+            List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getChildren();
+            assertEquals(1, childrenLst1.size());
+            String localName = childrenLst1.get(0).getNodeType().getLocalName();
+            if (localName.equals("lf11")) {
+                assertTrue(childrenLst1.get(0) instanceof SimpleNode);
+                lf11Found = true;
+            } else if (localName.equals("lflst11")) {
+                assertTrue(childrenLst1.get(0) instanceof SimpleNode);
+                assertEquals("45", ((SimpleNode<?>) childrenLst1.get(0)).getValue());
+                lf11Found = true;
+            } else if (localName.equals("cont11")) {
+                assertTrue(childrenLst1.get(0) instanceof CompositeNode);
+                cont11Found = true;
+            } else if (localName.equals("lst11")) {
+                lst11Found = true;
+                assertTrue(childrenLst1.get(0) instanceof CompositeNode);
+                assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getChildren().size());
+            }
+
+        }
+        assertTrue(lf11Found);
+        assertTrue(cont11Found);
+        assertTrue(lst11Found);
+    }
+
+    private void verifyCompositeNode(CompositeNode compositeNode, String namespace) {
+        boolean cont1Found = false;
+        boolean lst1Found = false;
+        boolean lflst1_1Found = false;
+        boolean lflst1_2Found = false;
+        boolean lf1Found = false;
+
+        assertEquals(namespace, compositeNode.getNodeType().getNamespace().toString());
+
+        for (Node<?> node : compositeNode.getChildren()) {
+            if (node.getNodeType().getLocalName().equals("cont1")) {
+                if (node instanceof CompositeNode) {
+                    cont1Found = true;
+                    assertEquals(0, ((CompositeNode) node).getChildren().size());
+                }
+            } else if (node.getNodeType().getLocalName().equals("lst1")) {
+                if (node instanceof CompositeNode) {
+                    lst1Found = true;
+                    assertEquals(0, ((CompositeNode) node).getChildren().size());
+                }
+            } else if (node.getNodeType().getLocalName().equals("lflst1")) {
+                if (node instanceof SimpleNode) {
+                    if (((SimpleNode<?>) node).getValue().equals("lflst1_1")) {
+                        lflst1_1Found = true;
+                    } else if (((SimpleNode<?>) node).getValue().equals("lflst1_2")) {
+                        lflst1_2Found = true;
+                    }
+                }
+
+            } else if (node.getNodeType().getLocalName().equals("lf1")) {
+                if (node instanceof SimpleNode) {
+                    if (((SimpleNode<?>) node).getValue().equals("lf1")) {
+                        lf1Found = true;
+                    }
+                }
+            }
+            assertEquals(namespace, node.getNodeType().getNamespace().toString());
+        }
+        assertTrue(cont1Found);
+        assertTrue(lst1Found);
+        assertTrue(lflst1_1Found);
+        assertTrue(lflst1_2Found);
+        assertTrue(lf1Found);
+    }
+
+    private CompositeNode compositeContainerFromJson(String jsonPath) {
+        return compositeContainerFromJson(jsonPath, false);
+    }
+
+    private CompositeNode compositeContainerFromJson(String jsonPath, boolean dummyNamespaces)
+            throws WebApplicationException {
+
+        JsonToCompositeNodeProvider jsonToCompositeNodeProvider = JsonToCompositeNodeProvider.INSTANCE;
+        InputStream jsonStream = FromJsonToCompositeNode.class.getResourceAsStream(jsonPath);
+        try {
+            CompositeNode compositeNode = jsonToCompositeNodeProvider
+                    .readFrom(null, null, null, null, null, jsonStream);
+            assertTrue(compositeNode instanceof CompositeNodeWrapper);
+            if (dummyNamespaces) {
+                try {
+                    TestUtils.addDummyNamespaceToAllNodes((CompositeNodeWrapper) compositeNode);
+                    return ((CompositeNodeWrapper) compositeNode).unwrap(null);
+                } catch (URISyntaxException e) {
+                    LOG.error(e.getMessage());
+                    assertTrue(e.getMessage(), false);
+                }
+            }
+            return compositeNode;
+        } catch (IOException e) {
+            LOG.error(e.getMessage());
+            assertTrue(e.getMessage(), false);
+        }
+        return null;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNode.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNode.java
new file mode 100644 (file)
index 0000000..093cac5
--- /dev/null
@@ -0,0 +1,253 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.net.URISyntaxException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.*;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.slf4j.*;
+
+public class FromXmlToCompositeNode {
+    private static Logger LOG = LoggerFactory.getLogger(FromXmlToCompositeNode.class);
+
+    /**
+     * top level element represents container. second level element is list with
+     * two elements.
+     */
+    @Test
+    public void testXmlDataContainer() {
+        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/data-container.xml", false);
+        assertNotNull(compNode);
+        DataSchemaNode dataSchemaNode = null;
+        try {
+            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-composite-node/data-container-yang");
+        } catch (FileNotFoundException e) {
+            LOG.error(e.getMessage());
+            assertTrue(false);
+        }
+
+        assertNotNull(dataSchemaNode);
+        TestUtils.supplementNamespace(dataSchemaNode, compNode);
+
+        String nameSpace = "data:container:yang";
+        assertEquals(nameSpace, compNode.getNodeType().getNamespace().toString());
+
+        verifyCommonPartAOfXml(compNode, "", nameSpace);
+    }
+
+    @Test
+    public void testXmlDataList() {
+        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/data-list.xml", false);
+        assertNotNull(compNode);
+
+        DataSchemaNode dataSchemaNode = null;
+        try {
+            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-composite-node/data-list-yang",
+                    "data-container-yang");
+        } catch (FileNotFoundException e) {
+            LOG.error(e.getMessage());
+        }
+        assertNotNull(dataSchemaNode);
+        TestUtils.supplementNamespace(dataSchemaNode, compNode);
+
+        String nameSpaceList = "data:list:yang";
+        String nameSpaceCont = "data:container:yang";
+        assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
+        assertEquals("cont", compNode.getNodeType().getLocalName());
+        assertEquals(3, compNode.getChildren().size());
+        CompositeNode lst1_1 = null;
+        CompositeNode lst1_2 = null;
+        int loopCount = 0;
+        for (Node<?> node : compNode.getChildren()) {
+            if (node.getNodeType().getLocalName().equals("lf1")) {
+                assertEquals(nameSpaceList, node.getNodeType().getNamespace().toString());
+                assertTrue(node instanceof SimpleNode<?>);
+                assertEquals("lf1", node.getValue());
+            } else {
+                assertTrue(node instanceof CompositeNode);
+                switch (loopCount++) {
+                case 0:
+                    lst1_1 = (CompositeNode) node;
+                    break;
+                case 1:
+                    lst1_2 = (CompositeNode) node;
+                    break;
+                }
+                assertEquals(nameSpaceCont, node.getNodeType().getNamespace().toString());
+            }
+        }
+        // lst1_1
+        verifyCommonPartAOfXml(lst1_1, "1", nameSpaceCont);
+        // :lst1_1
+
+        // lst1_2
+        SimpleNode<?> lflst11 = null;
+        CompositeNode cont11 = null;
+        for (Node<?> node : lst1_2.getChildren()) {
+            String nodeName = node.getNodeType().getLocalName();
+            if (nodeName.equals("lflst11")) {
+                assertTrue(node instanceof SimpleNode<?>);
+                lflst11 = (SimpleNode<?>) node;
+
+            } else if (nodeName.equals("cont11")) {
+                assertTrue(node instanceof CompositeNode);
+                cont11 = (CompositeNode) node;
+            }
+            assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
+        }
+        assertEquals("221", lflst11.getValue());
+
+        assertEquals(1, cont11.getChildren().size());
+        assertTrue(cont11.getChildren().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
+        assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
+        assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
+        assertEquals("100", cont11_lf111.getValue());
+        // :lst1_2
+
+    }
+
+    @Test
+    public void testXmlEmptyData() {
+        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/empty-data.xml", true);
+        assertEquals("cont", compNode.getNodeType().getLocalName());
+        SimpleNode<?> lf1 = null;
+        SimpleNode<?> lflst1_1 = null;
+        SimpleNode<?> lflst1_2 = null;
+        CompositeNode lst1 = null;
+        int lflst1Count = 0;
+        for (Node<?> node : compNode.getChildren()) {
+            if (node.getNodeType().getLocalName().equals("lf1")) {
+                assertTrue(node instanceof SimpleNode<?>);
+                lf1 = (SimpleNode<?>) node;
+            } else if (node.getNodeType().getLocalName().equals("lflst1")) {
+                assertTrue(node instanceof SimpleNode<?>);
+
+                switch (lflst1Count++) {
+                case 0:
+                    lflst1_1 = (SimpleNode<?>) node;
+                    break;
+                case 1:
+                    lflst1_2 = (SimpleNode<?>) node;
+                    break;
+                }
+            } else if (node.getNodeType().getLocalName().equals("lst1")) {
+                assertTrue(node instanceof CompositeNode);
+                lst1 = (CompositeNode) node;
+            }
+        }
+
+        assertNotNull(lf1);
+        assertNotNull(lflst1_1);
+        assertNotNull(lflst1_2);
+        assertNotNull(lst1);
+
+        assertEquals("", lf1.getValue());
+        assertEquals("", lflst1_1.getValue());
+        assertEquals("", lflst1_2.getValue());
+        assertEquals(1, lst1.getChildren().size());
+        assertEquals("lf11", lst1.getChildren().get(0).getNodeType().getLocalName());
+
+        assertTrue(lst1.getChildren().get(0) instanceof SimpleNode<?>);
+        assertEquals("", lst1.getChildren().get(0).getValue());
+
+    }
+
+    private void verifyCommonPartAOfXml(CompositeNode compNode, String suf, String nameSpace) {
+        SimpleNode<?> lf1suf = null;
+        SimpleNode<?> lflst1suf_1 = null;
+        SimpleNode<?> lflst1suf_2 = null;
+        SimpleNode<?> lflst1suf_3 = null;
+        CompositeNode cont1suf = null;
+        CompositeNode lst1suf = null;
+
+        int lflstCount = 0;
+
+        for (Node<?> node : compNode.getChildren()) {
+            String localName = node.getNodeType().getLocalName();
+            if (localName.equals("lf1" + suf)) {
+                assertTrue(node instanceof SimpleNode<?>);
+                lf1suf = (SimpleNode<?>) node;
+            } else if (localName.equals("lflst1" + suf)) {
+                assertTrue(node instanceof SimpleNode<?>);
+                switch (lflstCount++) {
+                case 0:
+                    lflst1suf_1 = (SimpleNode<?>) node;
+                    break;
+                case 1:
+                    lflst1suf_2 = (SimpleNode<?>) node;
+                    break;
+                case 2:
+                    lflst1suf_3 = (SimpleNode<?>) node;
+                    break;
+                }
+            } else if (localName.equals("lst1" + suf)) {
+                assertTrue(node instanceof CompositeNode);
+                lst1suf = (CompositeNode) node;
+            } else if (localName.equals("cont1" + suf)) {
+                assertTrue(node instanceof CompositeNode);
+                cont1suf = (CompositeNode) node;
+            }
+            assertEquals(nameSpace, node.getNodeType().getNamespace().toString());
+        }
+
+        assertNotNull(lf1suf);
+        assertNotNull(lflst1suf_1);
+        assertNotNull(lflst1suf_2);
+        assertNotNull(lflst1suf_3);
+        assertNotNull(lst1suf);
+        assertNotNull(cont1suf);
+
+        assertEquals("str0", lf1suf.getValue());
+        assertEquals("121", lflst1suf_1.getValue());
+        assertEquals("131", lflst1suf_2.getValue());
+        assertEquals("str1", lflst1suf_3.getValue());
+
+        assertEquals(1, lst1suf.getChildren().size());
+
+        assertTrue(lst1suf.getChildren().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> lst11_lf11 = (SimpleNode<?>) lst1suf.getChildren().get(0);
+        assertEquals(nameSpace, lst11_lf11.getNodeType().getNamespace().toString());
+        assertEquals("lf11" + suf, lst11_lf11.getNodeType().getLocalName());
+        assertEquals("str2", lst11_lf11.getValue());
+
+        assertTrue(cont1suf.getChildren().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
+        assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
+        assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
+        assertEquals("100", cont1_lf11.getValue());
+    }
+
+    private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) {
+        XmlToCompositeNodeProvider xmlToCompositeNodeProvider = XmlToCompositeNodeProvider.INSTANCE;
+        try {
+            InputStream xmlStream = FromXmlToCompositeNode.class.getResourceAsStream(xmlPath);
+            CompositeNode compositeNode = xmlToCompositeNodeProvider.readFrom(null, null, null, null, null, xmlStream);
+            if (dummyNamespaces) {
+                try {
+                    TestUtils.addDummyNamespaceToAllNodes((CompositeNodeWrapper) compositeNode);
+                    return ((CompositeNodeWrapper) compositeNode).unwrap(null);
+                } catch (URISyntaxException e) {
+                    LOG.error(e.getMessage());
+                    assertTrue(e.getMessage(), false);
+                }
+            }
+            return compositeNode;
+
+        } catch (WebApplicationException | IOException e) {
+            LOG.error(e.getMessage());
+            assertTrue(false);
+        }
+        return null;
+    }
+
+}
index 532e29df66dbe5962ab246e56b674710fede7622..3d06e4a759985f1eb938576b7bac10e9be9b8aae 100644 (file)
@@ -2,33 +2,30 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.*;
 import java.net.*;
 import java.sql.Date;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import javax.ws.rs.WebApplicationException;
 import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.*;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
-import org.opendaylight.controller.sal.rest.impl.*;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.*;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.*;
-import org.opendaylight.yangtools.yang.data.impl.*;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
 import org.opendaylight.yangtools.yang.model.api.*;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.slf4j.*;
 import org.w3c.dom.Document;
 
 final class TestUtils {
@@ -265,4 +262,80 @@ final class TestUtils {
     static QName buildQName(String name) {
         return buildQName(name, "", null);
     }
+
+    static void supplementNamespace(DataSchemaNode dataSchemaNode, CompositeNode compositeNode) {
+        RestconfImpl restconf = RestconfImpl.getInstance();
+
+        InstanceIdWithSchemaNode instIdAndSchema = new InstanceIdWithSchemaNode(mock(InstanceIdentifier.class),
+                dataSchemaNode);
+
+        ControllerContext controllerContext = mock(ControllerContext.class);
+        BrokerFacade broker = mock(BrokerFacade.class);
+
+        when(controllerContext.toInstanceIdentifier(any(String.class))).thenReturn(instIdAndSchema);
+        when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(
+                new DummyFuture());
+
+        restconf.setControllerContext(controllerContext);
+        restconf.setBroker(broker);
+
+        // method is called only because it contains call of method which
+        // supplement namespaces to compositeNode
+        restconf.createConfigurationData("something", compositeNode);
+    }
+
+    static DataSchemaNode obtainSchemaFromYang(String yangFolder) throws FileNotFoundException {
+        return obtainSchemaFromYang(yangFolder, null);
+    }
+
+    static DataSchemaNode obtainSchemaFromYang(String yangFolder, String moduleName) throws FileNotFoundException {
+        Set<Module> modules = null;
+        modules = TestUtils.loadModules(ToJsonBasicDataTypesTest.class.getResource(yangFolder).getPath());
+
+        if (modules == null) {
+            return null;
+        }
+        if (modules.size() < 1) {
+            return null;
+        }
+        
+        Module moduleRes = null;        
+        if (modules.size() > 1) {
+            if (moduleName == null) {
+                return null;
+            } else {
+                for (Module module: modules) {
+                    if (module.getName().equals(moduleName)) {
+                        moduleRes = module; 
+                    }
+                }
+                if (moduleRes == null) {
+                    return null;
+                }
+            }
+        } else {
+            moduleRes = modules.iterator().next();
+        }
+        
+        if (moduleRes.getChildNodes() == null) {
+            return null;
+        }
+
+        if (moduleRes.getChildNodes().size() != 1) {
+            return null;
+        }
+        DataSchemaNode dataSchemaNode = moduleRes.getChildNodes().iterator().next();
+        return dataSchemaNode;
+
+    }
+
+    static void addDummyNamespaceToAllNodes(NodeWrapper<?> wrappedNode) throws URISyntaxException {
+        wrappedNode.setNamespace(new URI(""));
+        if (wrappedNode instanceof CompositeNodeWrapper) {
+            for (NodeWrapper<?> childNodeWrapper : ((CompositeNodeWrapper) wrappedNode).getValues()) {
+                addDummyNamespaceToAllNodes(childNodeWrapper);
+            }
+        }
+    }
+
 }
index 8cdbf78db9a52fffee9255d330b471605f4ec25b..f88a335f18c9ac37927f34e973ab469ebaa0315c 100644 (file)
@@ -72,7 +72,8 @@ public class ToJsonBasicDataTypesTest {
         boolean lfbinaryChecked = false;
         // boolean lfref1Checked = false;
         boolean lfemptyChecked = false;
-
+        boolean lfstr1Checked = false;
+        
         while (jReader.hasNext()) {
             String keyName = jReader.nextName();
             JsonToken peek = null;
@@ -98,6 +99,10 @@ public class ToJsonBasicDataTypesTest {
                 assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
                 assertEquals("lfstr", jReader.nextString());
                 lfstrChecked = true;
+            } else if (keyName.equals("lfstr1")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+                assertEquals("", jReader.nextString());
+                lfstr1Checked = true;
             } else if (keyName.equals("lfbool1")) {
                 assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
                 assertEquals(true, jReader.nextBoolean());
@@ -167,6 +172,7 @@ public class ToJsonBasicDataTypesTest {
         assertTrue("lfbool1 wasn't checked", lfbool1Checked);
         assertTrue("lfbool2 wasn't checked", lfbool2Checked);
         assertTrue("lfstr wasn't checked", lfstrChecked);
+        assertTrue("lfstr1 wasn't checked", lfstr1Checked);
         assertTrue("lfbinary wasn't checked", lfbinaryChecked);
         assertTrue("lfempty wasn't checked", lfemptyChecked);
         // assertTrue("lfref1 wasn't checked", lfref1Checked);
index 9d004362d29d0b64b9a8636f51430ccfa46d8ca3..baf226712ffbb255550948c3c5f36160d4c30262 100644 (file)
@@ -13,6 +13,10 @@ import java.net.URLEncoder;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 
@@ -31,6 +35,7 @@ import org.glassfish.jersey.test.TestProperties;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -73,7 +78,7 @@ public class XmlProvidersTest extends JerseyTest {
         restconfImpl.setControllerContext(controllerContext);
     }
 
-//    @Before
+    @Before
     public void logs() {
         List<LogRecord> loggedRecords = getLoggedRecords();
         for (LogRecord l : loggedRecords) {
@@ -102,26 +107,32 @@ public class XmlProvidersTest extends JerseyTest {
     public void testXmlToCompositeNodeProvider() throws ParserConfigurationException, SAXException, IOException {
         URI uri = null;
         try {
-            uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+            uri = new URI("/config/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
         } catch (UnsupportedEncodingException | URISyntaxException e) {
             e.printStackTrace();
         }
         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
         final CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
-        when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(new RpcResult<CompositeNode>() {
-            
+        when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(new Future<RpcResult<TransactionStatus>>() {
+            @Override
+            public boolean cancel(boolean mayInterruptIfRunning) {
+                return false;
+            }
             @Override
-            public boolean isSuccessful() {
-                return true;
+            public boolean isCancelled() {
+                return false;
             }
-            
             @Override
-            public CompositeNode getResult() {
-                return loadedCompositeNode;
+            public boolean isDone() {
+                return false;
             }
-            
             @Override
-            public Collection<RpcError> getErrors() {
+            public RpcResult<TransactionStatus> get() throws InterruptedException, ExecutionException {
+                return null;
+            }
+            @Override
+            public RpcResult<TransactionStatus> get(long timeout, TimeUnit unit) throws InterruptedException,
+                    ExecutionException, TimeoutException {
                 return null;
             }
         });
@@ -132,7 +143,7 @@ public class XmlProvidersTest extends JerseyTest {
         Document doc = docBuilder.parse(xmlStream);
         
         Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).post(Entity.entity(TestUtils.getDocumentInPrintableForm(doc), new MediaType("application","vnd.yang.api+xml")));
-        assertEquals(200, response.getStatus());
+        assertEquals(204, response.getStatus());
     }
     
     @Test
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data.json
new file mode 100644 (file)
index 0000000..a6ad7f6
--- /dev/null
@@ -0,0 +1,6 @@
+{
+       "cont": {       
+               "lflst1":[],
+               "lflst2":[45]           
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data1.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data1.json
new file mode 100644 (file)
index 0000000..10d964d
--- /dev/null
@@ -0,0 +1,5 @@
+{
+       "cont": {       
+               "lf":                           
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/multiple-items-in-list.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/multiple-items-in-list.json
new file mode 100644 (file)
index 0000000..8e88266
--- /dev/null
@@ -0,0 +1,26 @@
+{
+       "lst":[
+               {
+                       "lst1": [
+                               {
+                                       "lf11":"lf11_1"
+                               },
+                               {
+                                       "lflst11":[
+                                               45
+                                       ]
+                               },
+                               {
+                                       "cont11":{
+                                       }
+                               },
+                               {
+                                       "lst11":[
+                                       {
+                                               }
+                                       ]
+                               }
+                       ]
+               }
+       ]
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container-yang/simple-container.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container-yang/simple-container.yang
new file mode 100644 (file)
index 0000000..ddd67f7
--- /dev/null
@@ -0,0 +1,20 @@
+module simple-data-types {
+  namespace "simple:data:types";  
+
+  prefix "smpdtp";
+  revision 2013-11-12 {    
+  }
+  
+  container cont {
+       container cont1 {
+       }
+       list lst1 {
+       }
+       leaf-list lflst1 {
+               type string;
+       }
+       leaf lf1 {
+               type string;
+       }
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container.json
new file mode 100644 (file)
index 0000000..1be4149
--- /dev/null
@@ -0,0 +1,15 @@
+{
+       "cont":{
+               "cont1":{
+               },
+               "lst1": [
+                       {
+                       }
+               ],
+               "lflst1":[
+                       "lflst1_1",
+                       "lflst1_2"
+               ],
+               "lf1":"lf1"
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list-yang/simple-list.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list-yang/simple-list.yang
new file mode 100644 (file)
index 0000000..af8edfa
--- /dev/null
@@ -0,0 +1,20 @@
+module simple-data-types {
+  namespace "simple:data:types";  
+
+  prefix "smpdtp";
+  revision 2013-11-12 {    
+  }
+  
+  list lst {
+       container cont1 {
+       }
+       list lst1 {
+       }
+       leaf-list lflst1 {
+               type string;
+       }
+       leaf lf1 {
+               type string;
+       }
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list.json
new file mode 100644 (file)
index 0000000..fee6baa
--- /dev/null
@@ -0,0 +1,17 @@
+{
+       "lst":[
+               {
+                       "cont1":{
+                       },
+                       "lst1": [
+                               {
+                               }
+                       ],
+                       "lflst1":[
+                               "lflst1_1",
+                               "lflst1_2"
+                       ],
+                       "lf1":"lf1"
+               }
+       ]
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level1.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level1.json
new file mode 100644 (file)
index 0000000..3ae3a72
--- /dev/null
@@ -0,0 +1,9 @@
+{
+
+       "lst":[
+               {
+               },
+               {
+               }
+       ]
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level2.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level2.json
new file mode 100644 (file)
index 0000000..f0f5540
--- /dev/null
@@ -0,0 +1,9 @@
+{
+
+       "cont": {
+       },
+       "lst":[
+               {
+               }
+       ]
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level3.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level3.json
new file mode 100644 (file)
index 0000000..7288969
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "lf":"hello"
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container-yang/data-container.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container-yang/data-container.yang
new file mode 100644 (file)
index 0000000..7c17bf9
--- /dev/null
@@ -0,0 +1,26 @@
+module data-container-yang {
+  namespace "data:container:yang";  
+
+  prefix "dtconyg";
+  revision 2013-11-19 {    
+  }
+  
+  container cont {
+       leaf lf1 {
+               type string;
+       }
+       leaf-list lflst1 {
+               type string;
+       }
+       list lst1 {
+               leaf lf11 {
+                       type string;
+               } 
+       }
+       container cont1 {
+               leaf lf11 {
+                       type uint8;
+               }
+       }
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container.xml
new file mode 100644 (file)
index 0000000..0c60fbc
--- /dev/null
@@ -0,0 +1,12 @@
+<cont>
+       <lf1>str0</lf1>
+       <lflst1>121</lflst1>
+       <lflst1>131</lflst1>
+       <lflst1>str1</lflst1>
+       <lst1>
+               <lf11>str2</lf11>
+       </lst1>                 
+       <cont1>
+               <lf11>100</lf11>
+       </cont1>
+</cont>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-container.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-container.yang
new file mode 100644 (file)
index 0000000..3df3413
--- /dev/null
@@ -0,0 +1,28 @@
+module data-container-yang {
+  namespace "data:container:yang";  
+
+  prefix "dtconyg";
+  revision 2013-11-19 {    
+  }
+  
+  container cont {     
+         list lst1 {
+               leaf lf11 {
+                       type string;
+               }
+               leaf-list lflst11 {
+                       type string;
+               }
+               list lst11 {
+                       leaf lf111 {
+                               type string;
+                       } 
+               }
+               container cont11 {
+                       leaf lf111 {
+                               type uint8;
+                       }
+               }
+         }  
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-list.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-list.yang
new file mode 100644 (file)
index 0000000..47e2a45
--- /dev/null
@@ -0,0 +1,22 @@
+module data-list-yang {
+  namespace "data:list:yang"; 
+  
+  prefix "dtlstyg";
+
+  import data-container-yang {
+       prefix "dtconyg";
+       revision-date 2013-11-19;
+  }
+  
+  
+  revision 2013-11-19 {    
+  }
+       
+
+
+  augment "/dtconyg:cont" {
+       leaf lf1 {
+               type string;
+       }
+  }    
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list.xml
new file mode 100644 (file)
index 0000000..cab23c6
--- /dev/null
@@ -0,0 +1,21 @@
+<cont>
+       <lst1>
+               <lf11>str0</lf11>
+               <lflst11>121</lflst11>
+               <lflst11>131</lflst11>
+               <lflst11>str1</lflst11>
+               <lst11>
+                       <lf111>str2</lf111>
+               </lst11>                        
+               <cont11>
+                       <lf111>100</lf111>
+               </cont11>
+       </lst1>
+       <lst1>
+               <lflst11>221</lflst11>
+               <cont11>
+                       <lf111>100</lf111>
+               </cont11>
+       </lst1> 
+       <lf1>lf1</lf1>
+</cont>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/empty-data.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/empty-data.xml
new file mode 100644 (file)
index 0000000..162a556
--- /dev/null
@@ -0,0 +1,8 @@
+<cont>
+       <lf1></lf1>
+       <lflst1></lflst1>
+       <lflst1></lflst1>
+       <lst1>          
+               <lf11></lf11>
+       </lst1>                 
+</cont>
index 4ad0983e0422ffe7523e408c2337ff634ac91679..010d3b1c2b374c1a9002877700bac6787ea6b676 100644 (file)
@@ -46,6 +46,9 @@ module simple-data-types {
          leaf lfstr {
                type string;
          }       
+         leaf lfstr1 {
+               type string;
+         }       
          leaf lfbool1 {
                type boolean;
          }       
index 1e83cb4f699d517c999eb8fb68bd98bc80afe49f..df00ca917e7d16f1e5f8a65bdaec9f10671cecc8 100644 (file)
@@ -11,6 +11,7 @@
        <lfnuint16Max>65535</lfnuint16Max>
        <lfnuint32Max>4294967295</lfnuint32Max>
        <lfstr>lfstr</lfstr>
+       <lfstr1></lfstr1>
        <lfbool1>true</lfbool1>
        <lfbool2>false</lfbool2>
        <lfbool3>bla</lfbool3>