Merge "Bug 1372 - toString methods in generated classes"
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / TransformerGenerator.xtend
index cd5d93a5648b1d187708ad91f4c7bf2fa5c2c1db..473c8e644c0749ad757c7f06b8578c3d4fd01fdc 100644 (file)
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl
 
+import com.google.common.base.Joiner
+import java.io.File
+import java.security.ProtectionDomain
+import java.util.AbstractMap.SimpleEntry
+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.Set
+import java.util.TreeSet
+import javassist.CannotCompileException
 import javassist.ClassPool
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils
 import javassist.CtClass
-import java.util.Map
-import org.opendaylight.yangtools.yang.common.QName
 import javassist.CtField
-import static javassist.Modifier.*
-import static org.opendaylight.yangtools.sal.binding.generator.impl.CodecMapping.*
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.sal.binding.model.api.Type
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
-import org.opendaylight.yangtools.binding.generator.util.Types
-import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
-import java.util.HashMap
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import javassist.CtMethod
 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.List
-import java.util.TreeSet
-import com.google.common.base.Joiner
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
-import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-import static org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils.*;
-import org.opendaylight.yangtools.yang.binding.BindingDeserializer
-import org.opendaylight.yangtools.yang.binding.BindingCodec
-import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.yangtools.binding.generator.util.Types
 import org.opendaylight.yangtools.sal.binding.generator.util.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.generator.util.SourceCodeGenerator
+import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGeneratorFactory
+import org.opendaylight.yangtools.sal.binding.generator.util.XtendHelper
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
 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.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.util.ClassLoaderUtils
 import org.opendaylight.yangtools.yang.binding.Augmentation
-import java.util.Iterator
+import org.opendaylight.yangtools.yang.binding.BindingCodec
+import org.opendaylight.yangtools.yang.binding.BindingDeserializer
+import org.opendaylight.yangtools.yang.binding.BindingMapping
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
-import java.util.concurrent.ConcurrentHashMap
-import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.*;
-import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
-import org.opendaylight.yangtools.yang.model.util.ExtendedType
-import org.opendaylight.yangtools.yang.model.util.EnumerationType
-import static com.google.common.base.Preconditions.*
-import org.opendaylight.yangtools.yang.model.api.SchemaPath
-import javassist.CtMethod
-import javassist.CannotCompileException
-import java.util.concurrent.locks.Lock
-import java.util.concurrent.Callable
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
-import java.util.HashSet
-import java.util.Collections
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit
-import java.util.Set
-import org.opendaylight.yangtools.sal.binding.generator.util.XtendHelper
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.binding.BindingMapping
 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition
+import org.opendaylight.yangtools.yang.model.util.EnumerationType
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.slf4j.LoggerFactory
+
+import static com.google.common.base.Preconditions.*
+import static javassist.Modifier.*
+import static org.opendaylight.yangtools.sal.binding.generator.impl.CodecMapping.*
 
-class TransformerGenerator {
+import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.*
 
-    private static val log = LoggerFactory.getLogger(TransformerGenerator)
+class TransformerGenerator extends AbstractTransformerGenerator {
+    private static val LOG = LoggerFactory.getLogger(TransformerGenerator)
 
     public static val STRING = Types.typeForClass(String);
     public static val BOOLEAN = Types.typeForClass(Boolean);
     public static val INTEGER = Types.typeForClass(Integer);
-    public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
-
+    public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier);
     //public static val DECIMAL = Types.typeForClass(Decimal);
     public static val LONG = Types.typeForClass(Long);
-
-    val ClassPool classPool
-    val extension JavassistUtils utils;
-
-    CtClass BINDING_CODEC
-
-    CtClass ctQName
+    public static val CLASS_TYPE = Types.typeForClass(Class);
 
     @Property
     var File classFileCapturePath;
 
-    @Property
-    var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
+    val CtClass BINDING_CODEC
+    val CtClass ctQName
 
-    @Property
-    var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+    val SourceCodeGeneratorFactory sourceCodeGeneratorFactory = new SourceCodeGeneratorFactory();
 
-    @Property
-    var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
-
-    @Property
-    var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
-
-    @Property
-    var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
-
-    @Property
-    var GeneratorListener listener;
-
-    @Property
-    var extension GeneratedClassLoadingStrategy classLoadingStrategy
-
-    public static val CLASS_TYPE = Types.typeForClass(Class);
-
-    public new(ClassPool pool) {
-        classPool = pool;
-        utils = new JavassistUtils(pool)
+    public new(TypeResolver typeResolver, ClassPool pool) {
+        super(typeResolver, pool)
 
         BINDING_CODEC = BindingCodec.asCtClass;
         ctQName = QName.asCtClass
-
-        this.classLoadingStrategy = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
     }
 
-    def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
-        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+    override transformerForImpl(Class inputType) {
+        return runOnClassLoader(inputType.classLoader) [ |
             val ret = getGeneratedClass(inputType)
             if (ret !== null) {
                 listener.onClassProcessed(inputType);
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
             val ref = Types.typeForClass(inputType)
-            val node = typeToSchemaNode.get(ref)
-            val typeSpecBuilder = typeToDefinition.get(ref)
+            val node = getSchemaNode(ref)
+            createMapping(inputType, node, null)
+            val typeSpecBuilder = getDefinition(ref)
             checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateTransformerFor(inputType, typeSpec, node);
@@ -149,16 +119,17 @@ class TransformerGenerator {
     }
 
     def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
-        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+        return runOnClassLoader(inputType.classLoader) [ |
+            createMapping(inputType, node, null)
             val ret = getGeneratedClass(inputType)
             if (ret !== null) {
                 listener.onClassProcessed(inputType);
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
             val ref = Types.typeForClass(inputType)
-            var typeSpecBuilder = typeToDefinition.get(ref)
+            var typeSpecBuilder = getDefinition(ref)
             if (typeSpecBuilder == null) {
-                typeSpecBuilder = pathToType.get(node.path);
+                typeSpecBuilder = getTypeBuilder(node.path);
             }
 
             checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
@@ -169,38 +140,41 @@ class TransformerGenerator {
         ]
     }
 
-    def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
-        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+    override augmentationTransformerForImpl(Class inputType) {
+        return runOnClassLoader(inputType.classLoader) [ |
+
             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 node = getAugmentation(ref)
+            val typeSpecBuilder = getDefinition(ref)
             val typeSpec = typeSpecBuilder.toInstance();
+            //mappingForNodes(node.childNodes, typeSpec.allProperties, bindingId)
             val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
             listener.onClassProcessed(inputType);
             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) [ |
+    override caseCodecForImpl(Class inputType, ChoiceCaseNode node) {
+        return runOnClassLoader(inputType.classLoader) [ |
+            createMapping(inputType, node, null)
             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 typeSpecBuilder = getDefinition(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) [ |
+    override keyTransformerForIdentifiableImpl(Class parentType) {
+        return runOnClassLoader(parentType.classLoader) [ |
             val inputName = parentType.name + "Key";
             val inputType = loadClass(inputName);
             val ret = getGeneratedClass(inputType)
@@ -208,29 +182,85 @@ class TransformerGenerator {
                 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 node = getSchemaNode(ref) as ListSchemaNode
+            val typeSpecBuilder = getDefinition(ref)
             val typeSpec = typeSpecBuilder.identifierDefinition;
             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
     }
 
+    private def void createMapping(Class<?> inputType, SchemaNode node, InstanceIdentifier<?> parentId) {
+        var ClassLoader cl = inputType.classLoader
+        if (cl === null) {
+            cl = Thread.currentThread.contextClassLoader
+        }
+        ClassLoaderUtils.withClassLoader(cl,
+            [ |
+                if (!(node instanceof DataNodeContainer)) {
+                    return null
+                }
+                var InstanceIdentifier<?> bindingId = getBindingIdentifierByPath(node.path)
+                if (bindingId != null) {
+                    return null
+                }
+                val ref = Types.typeForClass(inputType)
+                var typeSpecBuilder = getDefinition(ref)
+                if (typeSpecBuilder == null) {
+                    typeSpecBuilder = getTypeBuilder(node.path);
+                }
+                checkState(typeSpecBuilder !== null, "Could not find type definition for %s, $s", inputType.name, node);
+                val typeSpec = typeSpecBuilder.toInstance();
+                var InstanceIdentifier<?> parent
+                if (parentId == null) {
+                    bindingId = InstanceIdentifier.create(inputType as Class)
+                    parent = bindingId
+                    putPathToBindingIdentifier(node.path, bindingId)
+                } else {
+                    parent = putPathToBindingIdentifier(node.path, parentId, inputType)
+                }
+                val Map<String, Type> properties = typeSpec.allProperties
+                if (node instanceof DataNodeContainer) {
+                    mappingForNodes((node as DataNodeContainer).childNodes, properties, parent)
+                } else if (node instanceof ChoiceNode) {
+                    mappingForNodes((node as ChoiceNode).cases, properties, parent)
+                }
+                return null;
+            ])
+    }
+
+    private def void mappingForNodes(Collection<? extends DataSchemaNode> childNodes, Map<String, Type> properties,
+        InstanceIdentifier<?> parent) {
+        for (DataSchemaNode child : childNodes) {
+            val signature = properties.getFor(child)
+            if (signature != null) {
+                val Type childType = signature.value
+                var Class<?> childTypeClass = null;
+                if (child instanceof ListSchemaNode && childType instanceof ParameterizedType) {
+                    childTypeClass = loadClass((childType as ParameterizedType).actualTypeArguments.get(0))
+                } else {
+                    childTypeClass = loadClass(childType)
+                }
+                createMapping(childTypeClass, child, parent)
+            }
+        }
+    }
+
     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) [ |
+    override keyTransformerForIdentifierImpl(Class inputType) {
+        return runOnClassLoader(inputType.classLoader) [ |
             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 node = getSchemaNode(ref) as ListSchemaNode
+            val typeSpecBuilder = getDefinition(ref)
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
@@ -238,7 +268,7 @@ class TransformerGenerator {
     }
 
     private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
-        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+        return runOnClassLoader(inputType.classLoader) [ |
             val transformer = getGeneratedClass(inputType)
             if (transformer != null) {
                 return transformer;
@@ -278,7 +308,7 @@ class TransformerGenerator {
             baseType = baseType.baseType;
         }
         val finalType = baseType;
-        return withClassLoaderAndLock(cls.classLoader, lock) [ |
+        return runOnClassLoader(cls.classLoader) [ |
             val valueTransformer = generateValueTransformer(cls, type, finalType);
             return valueTransformer;
         ]
@@ -291,8 +321,8 @@ class TransformerGenerator {
             return transformer;
         }
 
-        return withClassLoaderAndLock(cls.classLoader, lock) [ |
-            val valueTransformer = generateValueTransformer(cls, type);
+        return runOnClassLoader(cls.classLoader) [ |
+            val valueTransformer = generateValueTransformer(cls, type, typeDefinition);
             return valueTransformer;
         ]
     }
@@ -300,17 +330,19 @@ class TransformerGenerator {
     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
         try {
 
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = typeSpec.allProperties;
             val ctCls = createClass(inputType.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
-                staticQNameField(node.QName);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+                staticQNameField(node.QName, sourceGenerator);
                 implementsType(BINDING_CODEC)
-                method(Object, "toDomStatic", QName, Object) [
+                method(Object, "toDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             «QName.name» _resultName;
                             if($1 != null) {
@@ -329,10 +361,11 @@ class TransformerGenerator {
                             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
                         }
                     '''
+                    setBodyChecked(body, sourceGenerator)
                 ]
-                method(Object, "fromDomStatic", QName, Object) [
+                method(Object, "fromDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             if($2 == null){
                                 return  null;
@@ -351,9 +384,10 @@ class TransformerGenerator {
                             return _value;
                         }
                     '''
+                    setBodyChecked(body, sourceGenerator)
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
                             «QName.name» _localQName = («QName.name») _input.getKey();
@@ -361,9 +395,10 @@ class TransformerGenerator {
                             return toDomStatic(_localQName,_keyValue);
                         }
                     '''
+                    setBodyChecked(body, sourceGenerator)
                 ]
                 method(Object, "deserialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             «QName.name» _qname = QNAME;
                             if($1 instanceof java.util.Map.Entry) {
@@ -372,10 +407,12 @@ class TransformerGenerator {
                             return fromDomStatic(_qname,$1);
                         }
                     '''
+                    setBodyChecked(body, sourceGenerator)
                 ]
             ]
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            sourceGenerator.outputGeneratedSource( ctCls )
+            LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
         } catch (Exception e) {
             processException(inputType, e);
@@ -386,18 +423,19 @@ class TransformerGenerator {
     private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
         ChoiceCaseNode node) {
         try {
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
 
             //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 implementsType(BINDING_CODEC)
-                staticQNameField(node.QName);
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, AUGMENTATION_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
-                method(Object, "toDomStatic", QName, Object) [
+                staticQNameField(node.QName, sourceGenerator);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+                method(Object, "toDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
                             java.util.List _childNodes = new java.util.ArrayList();
@@ -406,9 +444,10 @@ class TransformerGenerator {
                             return ($r) _childNodes;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator)
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             «QName.name» _localName = QNAME;
@@ -418,25 +457,29 @@ class TransformerGenerator {
                             return toDomStatic(_localName,_input.getValue());
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator)
                 ]
-                method(Object, "fromDomStatic", QName, Object) [
+                method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = deserializeBody(type, node)
+                    setBodyChecked( deserializeBody(type, node, getBindingIdentifierByPath(node.path)),
+                                    sourceGenerator )
                 ]
-                method(Object, "deserialize", Object) [
-                    bodyChecked = '''
+                method(Object, "deserialize", #[Object, InstanceIdentifier]) [
+                    val body = '''
                         {
                             //System.out.println("«type.name»#deserialize: " +$1);
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
-                            return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue());
+                            return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue(),$2);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator)
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
+            sourceGenerator.outputGeneratedSource( ctCls )
             listener?.onDataContainerCodecCreated(inputType, ret);
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -448,20 +491,24 @@ class TransformerGenerator {
         Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
         try {
 
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(node.QName);
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
-                staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                staticQNameField(node.QName, sourceGenerator);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
                 implementsType(BINDING_CODEC)
-                method(Object, "toDomStatic", QName, Object) [
+
+                method(Object, "toDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = serializeBodyFacade(typeSpec, node)
+                    setBodyChecked( serializeBodyFacade(typeSpec, node), sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             «QName.name» _localName = QNAME;
@@ -471,27 +518,35 @@ class TransformerGenerator {
                             return toDomStatic(_localName,_input.getValue());
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
-                method(Object, "fromDomStatic", QName, Object) [
+
+                method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = deserializeBody(typeSpec, node)
+                    setBodyChecked( deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path)),
+                                    sourceGenerator )
                 ]
-                method(Object, "deserialize", Object) [
-                    bodyChecked = '''
+
+                method(Object, "deserialize", #[Object, InstanceIdentifier]) [
+                    val body = '''
                         {
                             «QName.name» _qname = QNAME;
                             if($1 instanceof java.util.Map.Entry) {
                                 _qname = («QName.name») ((java.util.Map.Entry) $1).getKey();
                             }
-                            return fromDomStatic(_qname,$1);
+                            return fromDomStatic(_qname,$1,$2);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+
+            sourceGenerator.outputGeneratedSource( ctCls )
+
             listener?.onDataContainerCodecCreated(inputType, ret);
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -503,18 +558,21 @@ class TransformerGenerator {
         Class<?> inputType, GeneratedType type, AugmentationSchema node) {
         try {
 
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = type.allProperties
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(node.augmentationQName);
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, AUGMENTATION_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                staticQNameField(node.augmentationQName, sourceGenerator);
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
                 implementsType(BINDING_CODEC)
-                method(Object, "toDomStatic", QName, Object) [
+
+                method(Object, "toDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("Qname " + $1);
                             ////System.out.println("Value " + $2);
@@ -529,25 +587,28 @@ class TransformerGenerator {
                             return ($r) _childNodes;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val 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());
+                            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());
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
-                method(Object, "fromDomStatic", QName, Object) [
+
+                method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             «QName.name» _localQName = QNAME;
-                        
+
                             if($2 == null) {
                             return null;
                             }
@@ -556,9 +617,9 @@ class TransformerGenerator {
                             «type.builderName» _builder = new «type.builderName»();
                             boolean _is_empty = true;
                             «FOR child : node.childNodes»
-                            «val signature = properties.getFor(child)»
-                            «deserializeProperty(child, signature.value, signature.key)»
-                            _builder.«signature.key.toSetter»(«signature.key»);
+                                «val signature = properties.getFor(child)»
+                                «deserializeProperty(child, signature.value, signature.key)»
+                                _builder.«signature.key.toSetter»(«signature.key»);
                             «ENDFOR»
                             if(_is_empty) {
                             return null;
@@ -566,15 +627,21 @@ class TransformerGenerator {
                             return _builder.build();
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
-                method(Object, "deserialize", Object) [
-                    bodyChecked = '''
-                        return fromDomStatic(QNAME,$1);
+
+                method(Object, "deserialize", #[Object, InstanceIdentifier]) [
+                    val body = '''
+                        {
+                            return fromDomStatic(QNAME,$1,$2);
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+            sourceGenerator.outputGeneratedSource( ctCls )
             listener?.onDataContainerCodecCreated(inputType, ret);
             return ret;
         } catch (Exception e) {
@@ -587,64 +654,70 @@ class TransformerGenerator {
         Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
         try {
 
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             //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, IDENTITYREF_CODEC, BindingCodec)
-                staticField(it, CLASS_TO_CASE_MAP, Map)
-                staticField(it, COMPOSITE_TO_CASE, Map)
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, DISPATCH_CODEC, BindingCodec, sourceGenerator)
                 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
                 implementsType(BINDING_CODEC)
-                method(List, "toDomStatic", QName, Object) [
+                method(List, "toDomStatic", #[QName, Object]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val 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;
+                            if («DISPATCH_CODEC» == null) {
+                                throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
                             }
-                            java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
-                            Object _ret =  _codec.serialize(_input);
+                            java.util.Map.Entry _input = new «SimpleEntry.name»($1,$2);
+                            Object _ret =  «DISPATCH_CODEC».serialize(_input);
                             ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
                             return («List.name») _ret;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
-                        throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+                    val body = '''
+                        {
+                            throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
-                method(Object, "fromDomStatic", QName, Map) [
+                method(Object, "fromDomStatic", #[QName, Map, InstanceIdentifier]) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
-                            «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
-                            if(_codec != null) {
-                                return _codec.deserialize(new «SimpleEntry.name»($1,$2));
+                            if («DISPATCH_CODEC» == null) {
+                                throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
                             }
-                            return null;
+                            return «DISPATCH_CODEC».deserialize($2,$3);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
-                method(Object, "deserialize", Object) [
-                    bodyChecked = '''
-                        throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+                method(Object, "deserialize", #[Object, InstanceIdentifier]) [
+                    val body = '''
+                        {
+                            throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            sourceGenerator.outputGeneratedSource( ctCls )
             val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             listener?.onChoiceCodecCreated(inputType, ret, node);
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -666,8 +739,8 @@ class TransformerGenerator {
         return ret;
     }
 
-    private def String deserializeBody(GeneratedType type, SchemaNode node) {
-        val ret = deserializeBodyImpl(type, node);
+    private def String deserializeBody(GeneratedType type, SchemaNode node, InstanceIdentifier<?> bindingId) {
+        val ret = deserializeBodyImpl(type, node, bindingId);
         return ret;
     }
 
@@ -680,7 +753,7 @@ class TransformerGenerator {
         }
     }
 
-    private def String deserializeBodyWithAugmentations(GeneratedType type, DataNodeContainer node) '''
+    private def String deserializeBodyWithAugmentations(GeneratedType type, DataNodeContainer node, InstanceIdentifier<?> bindingId) '''
         {
             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
             if($2 == null) {
@@ -689,16 +762,16 @@ class TransformerGenerator {
             java.util.Map _compositeNode = (java.util.Map) $2;
             //System.out.println(_localQName + " " + _compositeNode);
             «type.builderName» _builder = new «type.builderName»();
-            «deserializeDataNodeContainerBody(type, node)»
-            «deserializeAugmentations»
+            «deserializeDataNodeContainerBody(type, node, bindingId
+            «type.deserializeAugmentations»
             return _builder.build();
         }
     '''
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
+    private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node, InstanceIdentifier<?> bindingId) '''
         {
             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
-        
+
             if($2 == null) {
             return null;
             }
@@ -708,7 +781,7 @@ class TransformerGenerator {
         }
     '''
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node, InstanceIdentifier<?> bindingId) '''
         {
             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
             if($2 == null) {
@@ -718,30 +791,30 @@ class TransformerGenerator {
             //System.out.println(_localQName + " " + _compositeNode);
             «type.builderName» _builder = new «type.builderName»();
             «deserializeKey(type, node)»
-            «deserializeDataNodeContainerBody(type, node)»
-            «deserializeAugmentations»
+            «deserializeDataNodeContainerBody(type, node, bindingId
+            «type.deserializeAugmentations»
             return _builder.build();
         }
     '''
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) {
-        return deserializeBodyWithAugmentations(type, node);
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node, InstanceIdentifier<?> bindingId) {
+        return deserializeBodyWithAugmentations(type, node, bindingId);
     }
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, NotificationDefinition node) {
-        return deserializeBodyWithAugmentations(type, node);
+    private def dispatch String deserializeBodyImpl(GeneratedType type, NotificationDefinition node, InstanceIdentifier<?> bindingId) {
+        return deserializeBodyWithAugmentations(type, node, bindingId);
     }
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) {
-        return deserializeBodyWithAugmentations(type, node);
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node, InstanceIdentifier<?> bindingId) {
+        return deserializeBodyWithAugmentations(type, node, bindingId);
     }
 
-    private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
-        deserializeNodeContainerBodyImpl(type, type.allProperties, node);
+    private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node, InstanceIdentifier<?> bindingId) {
+        deserializeNodeContainerBodyImpl(type, type.allProperties, node, bindingId);
     }
 
     private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
-        DataNodeContainer node) {
+        DataNodeContainer node, InstanceIdentifier<?> bindingId) {
         val ret = '''
             boolean _is_empty = true;
             «FOR child : node.childNodes»
@@ -755,8 +828,9 @@ class TransformerGenerator {
         return ret;
     }
 
-    def deserializeAugmentations() '''
-        java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
+    def deserializeAugmentations(GeneratedType type) '''
+        «InstanceIdentifier.resolvedName» iid = $3.builder().child(«type.resolvedName».class).build();
+        java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode,$3);
         if(_augmentation != null) {
             «Iterator.name» _entries = _augmentation.entrySet().iterator();
             while(_entries.hasNext()) {
@@ -785,13 +859,15 @@ class TransformerGenerator {
                 Object _listItem = _iterator.next();
                 _is_empty = false;
                 ////System.out.println("  item" + _listItem);
-                Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
+                «val param = type.actualTypeArguments.get(0)»
+                «InstanceIdentifier.resolvedName» iid = $3.builder().child(«param.resolvedName».class).build();
+                Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem,iid);
                 ////System.out.println("  value" + _value);
                 «propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
             }
         }
-        
+
         ////System.out.println(" list" + «propertyName»);
     '''
 
@@ -837,12 +913,13 @@ class TransformerGenerator {
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
             _is_empty = false;
             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
-            «propertyName» =  «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+            «InstanceIdentifier.resolvedName» iid = $3.builder().child(«type.resolvedName».class).build();
+            «propertyName» =  «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»,iid);
         }
     '''
 
     private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
-        «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
+        «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode,$3);
         if(«propertyName» != null) {
             _is_empty = false;
         }
@@ -857,14 +934,32 @@ class TransformerGenerator {
         («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
     '''
 
+    private def dispatch String deserializeValue(Type type, String domParameter, TypeDefinition<?> typeDef) {
+        if (INSTANCE_IDENTIFIER.equals(type)) {
+            return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
+        } else if (CLASS_TYPE.equals(type)) {
+            return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
+        } else if (typeDef!=null && typeDef instanceof EmptyTypeDefinition) {
+            if(domParameter == null) {
+                return ''' Boolean.FALSE '''
+            } else {
+                return ''' Boolean.TRUE '''
+            }
+        }
+        return '''(«type.resolvedName») «domParameter»'''
+    }
+
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
         Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
         try {
 
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             val returnType = typeSpec.valueReturnType;
             if (returnType == null) {
-                val ctCls = createDummyImplementation(inputType, typeSpec);
+                val ctCls = createDummyImplementation(inputType, typeSpec, sourceGenerator);
                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+                sourceGenerator.outputGeneratedSource( ctCls )
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
 
@@ -872,17 +967,17 @@ class TransformerGenerator {
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 if (inputType.isYangBindingAvailable) {
                     implementsType(BINDING_CODEC)
-                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
                     implementsType(BindingDeserializer.asCtClass)
                 }
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     val ctSpec = typeSpec.asCtClass;
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
@@ -894,20 +989,22 @@ class TransformerGenerator {
                             return _domValue;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             return toDomValue($1);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
@@ -916,20 +1013,24 @@ class TransformerGenerator {
                             return _value;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "deserialize", Object) [
-                    bodyChecked = '''{
+                    val body = '''
+                        {
                             return fromDomValue($1);
-                    }
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            sourceGenerator.outputGeneratedSource( ctCls )
+            LOG.debug("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;
@@ -939,23 +1040,25 @@ class TransformerGenerator {
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
         Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
         try {
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             val ctCls = createClass(typeSpec.codecClassName) [
                 val properties = typeSpec.allProperties;
                 val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type|type.QName.getterName];
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 if (inputType.isYangBindingAvailable) {
                     implementsType(BINDING_CODEC)
-                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
                     implementsType(BindingDeserializer.asCtClass)
                 }
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     val ctSpec = inputType.asCtClass;
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
@@ -970,24 +1073,26 @@ class TransformerGenerator {
                                 }
                             «ENDIF»
                             «ENDFOR»
-                        
+
                             return null;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             return toDomValue($1);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
@@ -998,20 +1103,24 @@ class TransformerGenerator {
                             return null;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "deserialize", Object) [
-                    bodyChecked = '''{
+                    val body = '''
+                        {
                             return fromDomValue($1);
-                    }
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            sourceGenerator.outputGeneratedSource( ctCls )
+            LOG.debug("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;
@@ -1021,28 +1130,30 @@ class TransformerGenerator {
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
         Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
         try {
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 if (inputType.isYangBindingAvailable) {
                     implementsType(BINDING_CODEC)
-                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
                     implementsType(BindingDeserializer.asCtClass)
                 }
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     val ctSpec = typeSpec.asCtClass;
-                    bodyChecked = '''
+                    val body = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
                             «HashSet.resolvedName» _value = new «HashSet.resolvedName»();
                             //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
-                        
+
                             «FOR bit : typeDef.bits»
                             «val getter = bit.getterName()»
                             if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
@@ -1051,25 +1162,27 @@ class TransformerGenerator {
                             «ENDFOR»
                             «Set.resolvedName» _domValue =  «Collections.resolvedName».unmodifiableSet(_value);
                             //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
-                        
+
                             return _domValue;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
+                    val body = '''
                         {
                             return toDomValue($1);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
-                    bodyChecked = '''
+                    val body = '''
                         {
                             //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-                        
+
                             if($1 == null) {
                             return null;
                             }
@@ -1077,24 +1190,28 @@ class TransformerGenerator {
                             «FOR bit : sortedBits»
                             Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
                             «ENDFOR»
-                        
+
                             return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "deserialize", Object) [
-                    bodyChecked = '''{
+                    val body = '''
+                        {
                             return fromDomValue($1);
-                    }
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            sourceGenerator.outputGeneratedSource( ctCls )
+            LOG.debug("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;
@@ -1120,42 +1237,48 @@ class TransformerGenerator {
         }
     }
 
-    private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
-        log.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
+    private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec,
+                                          SourceCodeGenerator sourceGenerator ) {
+        LOG.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
         return createClass(typeSpec.codecClassName) [
             if (object.isYangBindingAvailable) {
                 implementsType(BINDING_CODEC)
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
                 implementsType(BindingDeserializer.asCtClass)
             }
             //implementsType(BindingDeserializer.asCtClass)
             method(Object, "toDomValue", Object) [
                 modifiers = PUBLIC + FINAL + STATIC
-                bodyChecked = '''{
-                    if($1 == null) {
-                        return null;
-                    }
-                    return $1.toString();
-
+                val body = '''
+                    {
+                        if($1 == null) {
+                            return null;
+                        }
+                        return $1.toString();
                     }'''
+                setBodyChecked( body, sourceGenerator )
             ]
             method(Object, "serialize", Object) [
-                bodyChecked = '''
+                val body = '''
                     {
                         return toDomValue($1);
                     }
                 '''
+                setBodyChecked( body, sourceGenerator )
             ]
             method(Object, "fromDomValue", Object) [
                 modifiers = PUBLIC + FINAL + STATIC
-                bodyChecked = '''return null;'''
+                val body = '''return null;'''
+                setBodyChecked( body, sourceGenerator )
             ]
             method(Object, "deserialize", Object) [
-                bodyChecked = '''{
+                val body = '''
+                    {
                         return fromDomValue($1);
                     }
                     '''
+                setBodyChecked( body, sourceGenerator )
             ]
         ]
     }
@@ -1172,11 +1295,18 @@ class TransformerGenerator {
         return null;
     }
 
-    private def Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
-        try {
+    private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec, TypeDefinition<?> type) {
+        var EnumerationType enumSchemaType
+        if (type instanceof EnumerationType) {
+            enumSchemaType = type as EnumerationType
+        } else {
             val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
-            val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
-            val enumSchema = schema.baseType as EnumerationType;
+            val schema = getSchemaNode(typeRef) as ExtendedType;
+            enumSchemaType = schema.baseType as EnumerationType;
+        }
+        val enumSchema = enumSchemaType;
+        try {
+            val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
 
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
@@ -1184,28 +1314,33 @@ class TransformerGenerator {
                 //implementsType(BINDING_CODEC)
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''{
+                    val body = '''
+                        {
                             if($1 == null) {
                                 return null;
                             }
                             «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
                             «FOR en : enumSchema.values»
-                            if(«typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)».equals(_value)) {
+                            if(«typeSpec.resolvedName».«BindingMapping.getClassName(en.name)».equals(_value)) {
                                 return "«en.name»";
                             }
                             «ENDFOR»
                             return null;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "serialize", Object) [
-                    bodyChecked = '''
-                        return toDomValue($1);
+                    val body = '''
+                        {
+                            return toDomValue($1);
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    bodyChecked = '''
+                    val body = '''
                         {
                             if($1 == null) {
                                 return null;
@@ -1213,27 +1348,32 @@ class TransformerGenerator {
                             String _value = (String) $1;
                             «FOR en : enumSchema.values»
                                 if("«en.name»".equals(_value)) {
-                                    return «typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)»;
+                                    return «typeSpec.resolvedName».«BindingMapping.getClassName(en.name)»;
                                 }
                             «ENDFOR»
                             return null;
                         }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
                 method(Object, "deserialize", Object) [
-                    bodyChecked = '''
-                        return fromDomValue($1);
+                    val body = '''
+                        {
+                            return fromDomValue($1);
+                        }
                     '''
+                    setBodyChecked( body, sourceGenerator )
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            sourceGenerator.outputGeneratedSource( ctCls )
+            LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (CodeGenerationException 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;
@@ -1258,16 +1398,6 @@ class TransformerGenerator {
 
     }
 
-    private def dispatch String deserializeValue(Type type, String domParameter, TypeDefinition<?> typeDef) {
-        if (INSTANCE_IDENTIFIER.equals(type)) {
-            return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
-        } else if (CLASS_TYPE.equals(type)) {
-            return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
-        }
-        return '''(«type.resolvedName») «domParameter»'''
-
-    }
-
     /**
      * Default catch all
      *
@@ -1281,7 +1411,7 @@ class TransformerGenerator {
         _deserializeProperty(container, type.toInstance, propertyName)
     }
 
-    public static def toSetter(String it) {
+    static def toSetter(String it) {
 
         if (startsWith("is")) {
             return "set" + substring(2);
@@ -1302,11 +1432,13 @@ class TransformerGenerator {
     */
     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
 
-    private def staticQNameField(CtClass it, QName node) {
+    private def staticQNameField(CtClass it, QName node, SourceCodeGenerator sourceGenerator) {
         val field = new CtField(ctQName, "QNAME", it);
         field.modifiers = PUBLIC + FINAL + STATIC;
-        addField(field,
-            '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
+        val code = '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")'''
+        addField(field, code )
+
+        sourceGenerator.appendField( field, code );
     }
 
     private def String serializeBodyImpl(GeneratedType type, DataNodeContainer nodeContainer) '''
@@ -1358,14 +1490,14 @@ class TransformerGenerator {
         return ret;
     }
 
-    private def serializeAugmentations() '''
+    private static 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) {
+    private static def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
         var sig = map.get(node.getterName);
         if (sig != null) {
             return new SimpleEntry(node.getterName, sig);
@@ -1407,7 +1539,7 @@ class TransformerGenerator {
 
     private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
-        
+
         if(«propertyName» != null) {
             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
             Object _propValue = «serializeValue(type, propertyName, schema.type)»;
@@ -1425,19 +1557,19 @@ class TransformerGenerator {
     private def dispatch serializeValue(Enumeration type, String parameter, TypeDefinition<?> typeDefinition) {
         '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
     }
-    
+
     private def dispatch serializeValue(Type type, String parameter, EmptyTypeDefinition typeDefinition) {
         '''(«parameter».booleanValue() ? "" : null)'''
     }
-    
+
     private def dispatch serializeValue(Type signature, String property, TypeDefinition<?> typeDefinition) {
         serializeValue(signature,property)
     }
-    
+
     private def dispatch serializeValue(Type signature, String property, Void typeDefinition) {
         serializeValue(signature,property)
     }
-    
+
     private def dispatch serializeValue(Type signature, String property) {
         if (INSTANCE_IDENTIFIER == signature) {
             return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
@@ -1550,31 +1682,27 @@ class TransformerGenerator {
     }
 
     private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
-        log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
+        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);
+        LOG.error("Cannot compile DOM Codec for {}", inputType, e);
         val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
         throw exception;
     }
 
-    private def setBodyChecked(CtMethod method, String body) {
+    private def setBodyChecked(CtMethod method, String body, SourceCodeGenerator sourceGenerator ) {
         try {
             method.setBody(body);
+
+            sourceGenerator.appendMethod( method, body );
         } catch (CannotCompileException e) {
-            log.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
+            LOG.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
                 method.signature, e.message, body)
             throw e;
         }
     }
-
-    private def <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
-        appendClassLoaderIfMissing(cls);
-        ClassLoaderUtils.withClassLoaderAndLock(cls, lock, function);
-    }
-
 }
 
 @Data