Fixed bug in discovering JVM loaded case classes during code generation
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / dom / serializer / impl / TransformerGenerator.xtend
index 01390d7c41612e819b3cffc9964538f66263bf38..5bc2d70c6a97a6cfba93ff15ee065ecbae352ae8 100644 (file)
@@ -45,6 +45,25 @@ import org.opendaylight.yangtools.yang.binding.Augmentation
 import java.util.Iterator
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
 import java.util.concurrent.ConcurrentHashMap
+import static extension org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils.*;
+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.controller.sal.binding.impl.util.ClassLoaderUtils
+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.controller.sal.binding.codegen.impl.XtendHelper
 
 class TransformerGenerator {
 
@@ -74,6 +93,9 @@ class TransformerGenerator {
     @Property
     var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
 
+    @Property
+    var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
+
     @Property
     var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
 
@@ -83,6 +105,8 @@ class TransformerGenerator {
     @Property
     var GeneratorListener listener;
 
+    public static val CLASS_TYPE = Types.typeForClass(Class);
+
     public new(ClassPool pool) {
         classPool = pool;
         utils = new JavassistUtils(pool)
@@ -101,6 +125,7 @@ class TransformerGenerator {
             val ref = Types.typeForClass(inputType)
             val node = typeToSchemaNode.get(ref)
             val typeSpecBuilder = typeToDefinition.get(ref)
+            checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateTransformerFor(inputType, typeSpec, node);
             listener.onClassProcessed(inputType);
@@ -108,6 +133,30 @@ class TransformerGenerator {
         ]
     }
 
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            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)
+            if (typeSpecBuilder == null) {
+                typeSpecBuilder = pathToType.get(node.path);
+            }
+            var schemaNode = typeToSchemaNode.get(ref);
+            if(schemaNode === null) {
+                schemaNode = node;
+            }
+            checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateTransformerFor(inputType, typeSpec, schemaNode);
+            listener.onClassProcessed(inputType);
+            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)
@@ -201,20 +250,36 @@ class TransformerGenerator {
         keyTransformerFor(cls, type, node);
     }
 
-    private def serializer(Type type) {
+    private def serializer(Type type, DataSchemaNode node) {
         val cls = loadClassWithTCCL(type.resolvedName);
+        transformerFor(cls, node);
+    }
 
-        transformerFor(cls);
-
+    private def Class<?> valueSerializer(GeneratedTransferObject type, TypeDefinition<?> typeDefinition) {
+        val cls = loadClassWithTCCL(type.resolvedName);
+        val transformer = cls.generatedClass;
+        if (transformer !== null) {
+            return transformer;
+        }
+        var baseType = typeDefinition;
+        while (baseType.baseType != null) {
+            baseType = baseType.baseType;
+        }
+        val finalType = baseType;
+        return withClassLoaderAndLock(cls.classLoader, lock) [ |
+            val valueTransformer = generateValueTransformer(cls, type, finalType);
+            return valueTransformer;
+        ]
     }
 
-    private def Class<?> getValueSerializer(GeneratedTransferObject type) {
+    private def Class<?> valueSerializer(Enumeration type, TypeDefinition<?> typeDefinition) {
         val cls = loadClassWithTCCL(type.resolvedName);
         val transformer = cls.generatedClass;
         if (transformer !== null) {
             return transformer;
         }
-        return withClassLoaderAndLock(cls.classLoader,lock) [|
+
+        return withClassLoaderAndLock(cls.classLoader, lock) [ |
             val valueTransformer = generateValueTransformer(cls, type);
             return valueTransformer;
         ]
@@ -222,16 +287,18 @@ class TransformerGenerator {
 
     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = typeSpec.allProperties;
             val ctCls = createClass(inputType.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec)
                 staticQNameField(node.QName);
                 implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             «QName.name» _resultName;
                             if($1 != null) {
@@ -253,26 +320,28 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             if($2 == null){
                                 return  null;
                             }
                             «QName.name» _localQName = $1;
                             java.util.Map _compositeNode = (java.util.Map) $2;
+                            boolean _is_empty = true;
                             «FOR key : node.keyDefinition»
                                 «val propertyName = key.getterName»
                                 «val keyDef = node.getDataChildByName(key)»
                                 «val property = properties.get(propertyName)»
                                 «deserializeProperty(keyDef, property, propertyName)»;
                             «ENDFOR»
-                            «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
+                            «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
+                            keyConstructorList»);
                             return _value;
                         }
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
                             «QName.name» _localQName = («QName.name») _input.getKey();
@@ -282,13 +351,13 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomStatic(QNAME,$1);
                     '''
                 ]
             ]
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
         } catch (Exception e) {
             processException(inputType, e);
@@ -299,27 +368,29 @@ class TransformerGenerator {
     private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
         ChoiceCaseNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 implementsType(BINDING_CODEC)
-                staticQNameField(inputType);
+                staticQNameField(node.QName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
                             java.util.List _childNodes = new java.util.ArrayList();
                             «type.resolvedName» value = («type.resolvedName») $2;
-                            «transformDataContainerBody(type,type.allProperties, node)»
+                            «transformDataContainerBody(type, type.allProperties, node)»
                             return ($r) _childNodes;
                         }
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             «QName.name» _localName = QNAME;
@@ -332,21 +403,23 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = deserializeBody(type, node)
+                    bodyChecked = deserializeBody(type, node)
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
-                            
-                            return fromDomStatic(QNAME,$1);
+                            ////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());
                         }
                     '''
                 ]
             ]
 
-            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>>;
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
+            listener?.onDataContainerCodecCreated(inputType, ret);
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            return ret;
         } catch (Exception e) {
             processException(inputType, e);
             return null;
@@ -356,19 +429,21 @@ class TransformerGenerator {
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
         Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(inputType);
+                staticQNameField(node.QName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
                 implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = serializeBodyFacade(typeSpec, node)
+                    bodyChecked = serializeBodyFacade(typeSpec, node)
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             «QName.name» _localName = QNAME;
@@ -381,10 +456,10 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = deserializeBody(typeSpec, node)
+                    bodyChecked = deserializeBody(typeSpec, node)
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomStatic(QNAME,$1);
                     '''
                 ]
@@ -392,7 +467,7 @@ class TransformerGenerator {
 
             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)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -403,26 +478,28 @@ class TransformerGenerator {
     private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
         Class<?> inputType, GeneratedType type, AugmentationSchema node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = type.allProperties
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                staticQNameField(inputType);
+                staticQNameField(node.augmentationQName);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec)
                 implementsType(BINDING_CODEC)
                 method(Object, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
-                            //System.out.println("Qname " + $1);
-                            //System.out.println("Value " + $2);
-                            «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+                            ////System.out.println("Qname " + $1);
+                            ////System.out.println("Value " + $2);
+                            «QName.name» _resultName = «QName.name».create(QNAME,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»());
+                                ////System.out.println("«signature.key»" + value.«signature.key»());
                                 «serializeProperty(child, signature.value, signature.key)»
                             «ENDFOR»
                             return ($r) _childNodes;
@@ -430,7 +507,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                         java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                         «QName.name» _localName = QNAME;
@@ -443,7 +520,7 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             «QName.name» _localQName = QNAME;
                             
@@ -451,20 +528,23 @@ class TransformerGenerator {
                             return null;
                             }
                             java.util.Map _compositeNode = (java.util.Map) $2;
-                            //System.out.println(_localQName + " " + _compositeNode);
+                            System.out.println(_localQName + " " + _compositeNode);
                             «type.builderName» _builder = new «type.builderName»();
+                            boolean _is_empty = true;
                             «FOR child : node.childNodes»
                                 «val signature = properties.getFor(child)»
                                 «deserializeProperty(child, signature.value, signature.key)»
-                                
                                 _builder.«signature.key.toSetter»(«signature.key»);
                             «ENDFOR»
+                            if(_is_empty) {
+                                return null;
+                            }
                             return _builder.build();
                         }
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomStatic(QNAME,$1);
                     '''
                 ]
@@ -482,18 +562,20 @@ class TransformerGenerator {
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
         Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
         try {
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 //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,QNAME_TO_CASE_MAP,BindingCodec)
                 implementsType(BINDING_CODEC)
                 method(List, "toDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             if($2 == null) {
                                 return null;
@@ -506,19 +588,19 @@ class TransformerGenerator {
                             }
                             java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
                             Object _ret =  _codec.serialize(_input);
-                            //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
+                            ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
                             return («List.name») _ret;
                         }
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
                     '''
                 ]
                 method(Object, "fromDomStatic", QName, Map) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
                             if(_codec != null) {
@@ -529,7 +611,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
                     '''
                 ]
@@ -537,8 +619,8 @@ class TransformerGenerator {
 
             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)
+            listener?.onChoiceCodecCreated(inputType, ret, node);
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -594,6 +676,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
+            System.out.println(_localQName + " " + _compositeNode);
             «type.builderName» _builder = new «type.builderName»();
             «deserializeKey(type, node)»
             «deserializeDataNodeContainerBody(type, node)»
@@ -609,6 +692,7 @@ class TransformerGenerator {
                 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»
@@ -624,7 +708,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
-            //System.out.println(_localQName + " " + _compositeNode);
+            System.out.println(_localQName + " " + _compositeNode);
             «type.builderName» _builder = new «type.builderName»();
             «deserializeDataNodeContainerBody(type, node)»
             «deserializeAugmentations»
@@ -639,11 +723,13 @@ class TransformerGenerator {
     private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
         DataNodeContainer node) {
         val ret = '''
-            «FOR child : node.childNodes.filter[!augmenting]»
+            boolean _is_empty = true;
+            «FOR child : node.childNodes»
                 «val signature = properties.getFor(child)»
-                «deserializeProperty(child, signature.value, signature.key)»
-                
-                _builder.«signature.key.toSetter»(«signature.key»);
+                «IF signature !== null»
+                    «deserializeProperty(child, signature.value, signature.key)»
+                    _builder.«signature.key.toSetter»(«signature.key»);
+                «ENDIF»
             «ENDFOR»
         '''
         return ret;
@@ -655,10 +741,12 @@ class TransformerGenerator {
             «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());
+                ////System.out.println("Aug. key:" + _entry.getKey());
                 Class _type = (Class) _entry.getKey();
                 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
-                _builder.addAugmentation(_type,_value);
+                if(_value != null) {
+                    _builder.addAugmentation(_type,_value);
+                }
             }
         }
     '''
@@ -667,7 +755,7 @@ class TransformerGenerator {
         String propertyName) '''
         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
             localName»"));
-        //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
+        ////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();
@@ -675,15 +763,16 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                //System.out.println("  item" + _listItem);
-                Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
-                //System.out.println("  value" + _value);
+                _is_empty = false;
+                ////System.out.println("  item" + _listItem);
+                Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
+                ////System.out.println("  value" + _value);
                 «propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
             }
         }
         
-        //System.out.println(" list" + «propertyName»);
+        ////System.out.println(" list" + «propertyName»);
     '''
 
     private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
@@ -696,10 +785,11 @@ class TransformerGenerator {
             java.util.Iterator _iterator = _dom_«propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
+                _is_empty = false;
                 Object _listItem = _iterator.next();
                 if(_listItem instanceof java.util.Map.Entry) {
                     Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
-                    Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
+                    Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue", schema.type)»;
                     «propertyName».add(_value);
                 }
                 _hasNext = _iterator.hasNext();
@@ -712,9 +802,10 @@ class TransformerGenerator {
             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
         «type.resolvedName» «propertyName» = null;
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+            _is_empty = false;
             java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
             Object _inner_value = _dom_«propertyName».getValue();
-            «propertyName» = «deserializeValue(type, "_inner_value")»;
+            «propertyName» = «deserializeValue(type, "_inner_value", schema.type)»;
         }
     '''
 
@@ -724,22 +815,30 @@ class TransformerGenerator {
             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
         «type.resolvedName» «propertyName» = null;
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
-            
+            _is_empty = false;
             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
-            «propertyName» =  «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+            «propertyName» =  «type.serializer(schema).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);
+        «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
+        if(«propertyName» != null) {
+            _is_empty = false;
+        }
     '''
 
-    private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
-        («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
+    private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter,
+        TypeDefinition<?> typeDefinition) '''
+        («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
+    '''
+
+    private def dispatch String deserializeValue(Enumeration type, String domParameter, TypeDefinition<?> typeDefinition) '''
+        («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
     '''
 
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
-        Class<?> inputType, GeneratedTransferObject typeSpec) {
+        Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
         try {
 
             val returnType = typeSpec.valueReturnType;
@@ -748,41 +847,36 @@ class TransformerGenerator {
                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
-            var hasBinding = false;
-            try {
-                val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
-                hasBinding = bindingCodecClass !== null;
-            } catch (ClassNotFoundException e) {
-                hasBinding = false;
-            }
-            val hasYangBinding = hasBinding
+
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
-                if(hasYangBinding) {
+                if (inputType.isYangBindingAvailable) {
                     implementsType(BINDING_CODEC)
                     staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
                     implementsType(BindingDeserializer.asCtClass)
                 }
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    val ctSpec = typeSpec.asCtClass;
+                    bodyChecked = '''
                         {
-                            //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
                             }
                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
-                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
                             «returnType.resolvedName» _value =  _encapsulatedValue.getValue();
-                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
-                            Object _domValue = «serializeValue(returnType, "_value")»;
+                            ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+                            Object _domValue = «serializeValue(returnType, "_value", null)»;
                             return _domValue;
                         }
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             return toDomValue($1);
                         }
@@ -790,21 +884,21 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
-                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
                             }
-                            «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
+                            «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1", null)»;
                             «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
                             return _value;
                         }
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''{
+                    bodyChecked = '''{
                             return fromDomValue($1);
                     }
                     '''
@@ -812,7 +906,7 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            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);
@@ -820,21 +914,215 @@ class TransformerGenerator {
             exception.addSuppressed(e);
             throw exception;
         }
+    }
+
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
+        try {
+            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)
+                    implementsType(BindingDeserializer.asCtClass)
+                }
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val ctSpec = inputType.asCtClass;
+                    
+                    bodyChecked = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+                            «FOR property : properties.entrySet»
+                                «IF property.key != "getValue"»
+                                    «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.
+                            key»();
+                                    if(«property.key» != null) { 
+                                        return «serializeValue(property.value, property.key, getterToTypeDefinition.get(property.key))»;
+                                    }
+                                «ENDIF»
+                            «ENDFOR»
+                            
+                            return null;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    bodyChecked = '''
+                        {
+                            return toDomValue($1);
+                        }
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    bodyChecked = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            if($1 instanceof String) {
+                                String _simpleValue = (String) $1;
+                                return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
+                            }
+                            return null;
+                        }
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    bodyChecked = '''{
+                            return fromDomValue($1);
+                    }
+                    '''
+                ]
+            ]
 
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            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);
+            val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
+        try {
+            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)
+                    implementsType(BindingDeserializer.asCtClass)
+                }
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val ctSpec = typeSpec.asCtClass;
+                    bodyChecked = '''
+                        {
+                            ////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»())) {
+                                    _value.add("«bit.name»");
+                                }
+                            «ENDFOR»
+                            «Set.resolvedName» _domValue =  «Collections.resolvedName».unmodifiableSet(_value);
+                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
+                            
+                            return _domValue;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    bodyChecked = '''
+                        {
+                            return toDomValue($1);
+                        }
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
+                    bodyChecked = '''
+                        {
+                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            «Set.resolvedName» _domValue = («Set.resolvedName») $1;
+                            «FOR bit : sortedBits»
+                                Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
+                            «ENDFOR»
+                            
+                            return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
+                        }
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    bodyChecked = '''{
+                            return fromDomValue($1);
+                    }
+                    '''
+                ]
+            ]
+
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            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);
+            val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+    def String getPropertyName(Bit bit) {
+        '''_«BindingGeneratorUtil.parseToValidParamName(bit.name)»'''
+    }
+
+    def String getterName(Bit bit) {
+
+        val paramName = BindingGeneratorUtil.parseToValidParamName(bit.name);
+        return '''is«paramName.toFirstUpper»''';
+    }
+
+    def boolean isYangBindingAvailable(Class<?> class1) {
+        try {
+            val bindingCodecClass = class1.classLoader.loadClass(BINDING_CODEC.name);
+            return bindingCodecClass !== null;
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
     }
 
     private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
         log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
         return createClass(typeSpec.codecClassName) [
-            //staticField(Map,"AUGMENTATION_SERIALIZERS");
-            implementsType(BINDING_CODEC)
-            implementsType(BindingDeserializer.asCtClass)
+            if (object.isYangBindingAvailable) {
+                implementsType(BINDING_CODEC)
+                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                implementsType(BindingDeserializer.asCtClass)
+            }
+            //implementsType(BindingDeserializer.asCtClass)
             method(Object, "toDomValue", Object) [
                 modifiers = PUBLIC + FINAL + STATIC
-                body = '''return null;'''
+                bodyChecked = '''{
+                    if($1 == null) {
+                        return null;
+                    }
+                    return $1.toString();
+                    
+                    }'''
             ]
             method(Object, "serialize", Object) [
-                body = '''
+                bodyChecked = '''
                     {
                         return toDomValue($1);
                     }
@@ -842,10 +1130,10 @@ class TransformerGenerator {
             ]
             method(Object, "fromDomValue", Object) [
                 modifiers = PUBLIC + FINAL + STATIC
-                body = '''return null;'''
+                bodyChecked = '''return null;'''
             ]
             method(Object, "deserialize", Object) [
-                body = '''{
+                bodyChecked = '''{
                         return fromDomValue($1);
                     }
                     '''
@@ -865,49 +1153,63 @@ class TransformerGenerator {
         return null;
     }
 
-    private def dispatch Class<?> generateValueTransformer(
-        Class<?> inputType, Enumeration typeSpec) {
+    private def Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
         try {
+            val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
+            val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
+            val enumSchema = schema.baseType as EnumerationType;
+
             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 //implementsType(BINDING_CODEC)
-                
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
-                        if($1 == null) {
+                    bodyChecked = '''{
+                            if($1 == null) {
+                                return null;
+                            }
+                            «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+                            «FOR en : enumSchema.values»
+                            if(«typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)».equals(_value)) {
+                                return "«en.name»";
+                            }
+                            «ENDFOR»
                             return null;
                         }
-                        «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
-                        return _value.getValue();
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return toDomValue($1);
                     '''
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
-                        if($1 == null) {
+                    bodyChecked = '''
+                        {
+                            if($1 == null) {
+                                return null;
+                            }
+                            String _value = (String) $1;
+                            «FOR en : enumSchema.values»
+                                if("«en.name»".equals(_value)) {
+                                    return «typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)»;
+                                }
+                            «ENDFOR»
                             return null;
                         }
-                        _simpleValue = null;
-                        «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
-                        return _value;
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomValue($1);
                     '''
                 ]
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (CodeGenerationException e) {
             throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
@@ -937,12 +1239,12 @@ class TransformerGenerator {
 
     }
 
-    private def dispatch String deserializeValue(Type type, String 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»)'''
         }
-
         return '''(«type.resolvedName») «domParameter»'''
 
     }
@@ -981,12 +1283,6 @@ class TransformerGenerator {
     */
     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
 
-    private def staticQNameField(CtClass it, Class<?> node) {
-        val field = new CtField(ctQName, "QNAME", it);
-        field.modifiers = PUBLIC + FINAL + STATIC;
-        addField(field, '''«node.name».QNAME''')
-    }
-
     private def staticQNameField(CtClass it, QName node) {
         val field = new CtField(ctQName, "QNAME", it);
         field.modifiers = PUBLIC + FINAL + STATIC;
@@ -999,7 +1295,7 @@ class TransformerGenerator {
             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1010,7 +1306,7 @@ class TransformerGenerator {
             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1021,7 +1317,7 @@ class TransformerGenerator {
         «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             «type.resolvedName» value = («type.resolvedName») $2;
-            «transformDataContainerBody(type,type.allProperties, node)»
+            «transformDataContainerBody(type, type.allProperties, node)»
             «serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1036,18 +1332,20 @@ class TransformerGenerator {
         }
     '''
 
-    private def transformDataContainerBody(Type type,Map<String, Type> properties, DataNodeContainer node) {
+    private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
         val ret = '''
-            «FOR child : node.childNodes.filter[!augmenting]»
-                «var signature = properties.getFor(child)»
-                //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
-                «serializeProperty(child, signature.value, signature.key)»
+            «FOR child : node.childNodes»
+                «val signature = properties.getFor(child)»
+                «IF signature !== null»
+                    ////System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
+                    «serializeProperty(child, signature.value, signature.key)»
+                «ENDIF»
             «ENDFOR»
         '''
         return ret;
     }
 
-    def serializeAugmentations() '''
+    private def serializeAugmentations() '''
         java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
         if(_augmentations != null) {
             _childNodes.addAll(_augmentations);
@@ -1055,12 +1353,15 @@ class TransformerGenerator {
     '''
 
     def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
-        val sig = map.get(node.getterName);
-        if (sig == null) {
-
+        var sig = map.get(node.getterName);
+        if (sig != null) {
+            return new SimpleEntry(node.getterName, sig);
+        }
+        sig = map.get(node.booleanGetterName);
+        if (sig != null) {
             return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
         }
-        return new SimpleEntry(node.getterName, sig);
+        return null;
     }
 
     private static def String getBooleanGetterName(DataSchemaNode node) {
@@ -1078,12 +1379,13 @@ class TransformerGenerator {
     private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
         String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
+        ////System.out.println("«propertyName»:" + «propertyName»);
         if(«propertyName» != null) {
             java.util.Iterator _iterator = «propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
+                Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
                 _childNodes.add(_domValue);
                 _hasNext = _iterator.hasNext();
             }
@@ -1095,7 +1397,7 @@ class TransformerGenerator {
         
         if(«propertyName» != null) {
             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
-            Object _propValue = «serializeValue(type, propertyName)»;
+            Object _propValue = «serializeValue(type, propertyName, schema.type)»;
             if(_propValue != null) {
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
                 _childNodes.add(_domValue);
@@ -1103,12 +1405,22 @@ class TransformerGenerator {
         }
     '''
 
-    private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
-        resolvedName».toDomValue(«parameter»)'''
+    private def dispatch serializeValue(GeneratedTransferObject type, String parameter, TypeDefinition<?> typeDefinition) {
+        '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+    }
 
-    private def dispatch serializeValue(Type signature, String property) {
+    private def dispatch serializeValue(Enumeration type, String parameter, TypeDefinition<?> typeDefinition) {
+        '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+    }
+
+    private def dispatch serializeValue(Type signature, String property, TypeDefinition<?> typeDefinition) {
         if (INSTANCE_IDENTIFIER == signature) {
             return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
+        } else if (CLASS_TYPE.equals(signature)) {
+            return '''(«QName.resolvedName») «IDENTITYREF_CODEC».serialize(«property»)'''
+        }
+        if ("char[]" == signature.name) {
+            return '''new String(«property»)''';
         }
         return '''«property»''';
     }
@@ -1122,7 +1434,7 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
+                Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem", schema.type)»;
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
                 _childNodes.add(_domValue);
                 _hasNext = _iterator.hasNext();
@@ -1134,7 +1446,7 @@ class TransformerGenerator {
         String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
         if(«propertyName» != null) {
-            java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
             _childNodes.addAll(domValue);
         }
     '''
@@ -1160,7 +1472,7 @@ class TransformerGenerator {
         String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
         if(«propertyName» != null) {
-            Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
             _childNodes.add(domValue);
         }
     '''
@@ -1223,6 +1535,21 @@ class TransformerGenerator {
         throw exception;
     }
 
+    private def setBodyChecked(CtMethod method, String body) {
+        try {
+            method.setBody(body);
+        } catch (CannotCompileException e) {
+            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