Merge "Fixed netconf monitoring."
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / dom / serializer / impl / TransformerGenerator.xtend
index ab2e96f05c09b0e79502547e9502ffc697dd8b2b..4271ef9c1a9bb5824f04673cbcf1e86f466c7c52 100644 (file)
@@ -46,6 +46,16 @@ 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
 
 class TransformerGenerator {
 
@@ -75,6 +85,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();
 
@@ -84,6 +97,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)
@@ -102,6 +117,27 @@ 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);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    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);
+            }
+            checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateTransformerFor(inputType, typeSpec, node);
             listener.onClassProcessed(inputType);
@@ -202,11 +238,9 @@ 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);
-
+        transformerFor(cls, node);
     }
 
     private def Class<?> getValueSerializer(GeneratedTransferObject type) {
@@ -221,6 +255,19 @@ class TransformerGenerator {
         ]
     }
 
+    private def Class<?> getValueSerializer(Enumeration type) {
+        val cls = loadClassWithTCCL(type.resolvedName);
+        val transformer = cls.generatedClass;
+        if (transformer !== null) {
+            return transformer;
+        }
+
+        return withClassLoaderAndLock(cls.classLoader, lock) [ |
+            val valueTransformer = generateValueTransformer(cls, type);
+            return valueTransformer;
+        ]
+    }
+
     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
         try {
 
@@ -229,11 +276,12 @@ class TransformerGenerator {
             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) {
@@ -255,7 +303,7 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             if($2 == null){
                                 return  null;
@@ -276,7 +324,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
                             «QName.name» _localQName = («QName.name») _input.getKey();
@@ -286,7 +334,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomStatic(QNAME,$1);
                     '''
                 ]
@@ -311,9 +359,10 @@ class TransformerGenerator {
                 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();
@@ -324,7 +373,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             «QName.name» _localName = QNAME;
@@ -337,21 +386,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)
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
+            listener?.onDataContainerCodecCreated(inputType, ret);
             log.info("DOM Codec for {} was generated {}", inputType, ret)
-            return ret as Class<? extends BindingCodec<Object, Object>>;
+            return ret;
         } catch (Exception e) {
             processException(inputType, e);
             return null;
@@ -367,14 +418,15 @@ class TransformerGenerator {
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 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;
@@ -387,10 +439,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);
                     '''
                 ]
@@ -417,14 +469,15 @@ class TransformerGenerator {
                 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());
+                            «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»
@@ -437,7 +490,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                         java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                         «QName.name» _localName = QNAME;
@@ -450,7 +503,7 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomStatic", QName, Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             «QName.name» _localQName = QNAME;
                             
@@ -474,7 +527,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         return fromDomStatic(QNAME,$1);
                     '''
                 ]
@@ -498,13 +551,14 @@ class TransformerGenerator {
                 //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;
@@ -523,13 +577,13 @@ class TransformerGenerator {
                     '''
                 ]
                 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) {
@@ -540,7 +594,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
                     '''
                 ]
@@ -548,7 +602,7 @@ 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);
+            listener?.onChoiceCodecCreated(inputType, ret, node);
             log.info("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
@@ -692,7 +746,7 @@ class TransformerGenerator {
                 Object _listItem = _iterator.next();
                 _is_empty = false;
                 //System.out.println("  item" + _listItem);
-                Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+                Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
                 //System.out.println("  value" + _value);
                 «propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
@@ -744,12 +798,12 @@ 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.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;
         }
@@ -759,6 +813,10 @@ class TransformerGenerator {
         («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
     '''
 
+    private def dispatch String deserializeValue(Enumeration type, String domParameter) '''
+        («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
+    '''
+
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
         Class<?> inputType, GeneratedTransferObject typeSpec) {
         try {
@@ -769,24 +827,24 @@ 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;
+            if (returnType.name == 'char[]') {
+                val ctCls = createUnionImplementation(inputType, typeSpec);
+                val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
-            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);
                             
@@ -803,7 +861,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "serialize", Object) [
-                    body = '''
+                    bodyChecked = '''
                         {
                             return toDomValue($1);
                         }
@@ -811,7 +869,7 @@ class TransformerGenerator {
                 ]
                 method(Object, "fromDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
-                    body = '''
+                    bodyChecked = '''
                         {
                             //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
                             
@@ -825,7 +883,7 @@ class TransformerGenerator {
                     '''
                 ]
                 method(Object, "deserialize", Object) [
-                    body = '''{
+                    bodyChecked = '''{
                             return fromDomValue($1);
                     }
                     '''
@@ -844,18 +902,104 @@ class TransformerGenerator {
 
     }
 
+    def createUnionImplementation(Class<?> inputType, GeneratedTransferObject typeSpec) {
+        return createClass(typeSpec.codecClassName) [
+            val properties = typeSpec.allProperties;
+            //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)»;
+                                }
+                            «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);
+                    }
+                    '''
+            ]
+        ]
+    }
+
+    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);
                     }
@@ -863,10 +1007,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);
                     }
                     '''
@@ -888,6 +1032,9 @@ class TransformerGenerator {
 
     private def dispatch 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) [
@@ -895,32 +1042,44 @@ class TransformerGenerator {
                 //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);
                     '''
                 ]
@@ -959,10 +1118,10 @@ class TransformerGenerator {
 
     private def dispatch String deserializeValue(Type type, String domParameter) {
         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»'''
 
     }
@@ -1103,7 +1262,7 @@ class TransformerGenerator {
             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();
             }
@@ -1126,9 +1285,16 @@ class TransformerGenerator {
     private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
         resolvedName».toDomValue(«parameter»)'''
 
+    private def dispatch serializeValue(Enumeration type, String parameter) '''«type.valueSerializer.resolvedName».toDomValue(«parameter»)'''
+
     private def dispatch serializeValue(Type signature, String property) {
         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»''';
     }
@@ -1154,7 +1320,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);
         }
     '''
@@ -1180,7 +1346,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);
         }
     '''
@@ -1243,6 +1409,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