Merge "Ganymed ChannelManager hack for subsystem command"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / dom / serializer / impl / TransformerGenerator.xtend
1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
2
3 import javassist.ClassPool
4 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
5 import org.opendaylight.yangtools.yang.model.api.SchemaNode
6 import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
7 import javassist.CtClass
8 import java.util.Map
9 import org.opendaylight.yangtools.yang.common.QName
10 import javassist.CtField
11 import static javassist.Modifier.*
12 import static org.opendaylight.controller.sal.binding.dom.serializer.impl.CodecMapping.*
13 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
14 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
15 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
16 import org.opendaylight.yangtools.sal.binding.model.api.Type
17 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
18 import org.opendaylight.yangtools.binding.generator.util.Types
19 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
20 import java.util.HashMap
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
22 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
24 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
25 import java.util.List
26 import java.util.TreeSet
27 import com.google.common.base.Joiner
28 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
29 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
30 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
31 import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*;
32 import org.opendaylight.yangtools.yang.binding.BindingDeserializer
33 import org.opendaylight.yangtools.yang.binding.BindingCodec
34 import org.slf4j.LoggerFactory
35 import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
36 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
37 import java.security.ProtectionDomain
38 import java.io.File
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
40 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
41 import java.util.Map.Entry
42 import java.util.AbstractMap.SimpleEntry
43 import org.opendaylight.yangtools.yang.binding.DataObject
44 import org.opendaylight.yangtools.yang.binding.Augmentation
45 import java.util.Iterator
46 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
47 import java.util.concurrent.ConcurrentHashMap
48
49 class TransformerGenerator {
50
51     private static val log = LoggerFactory.getLogger(TransformerGenerator)
52
53     public static val STRING = Types.typeForClass(String);
54     public static val BOOLEAN = Types.typeForClass(Boolean);
55     public static val INTEGER = Types.typeForClass(Integer);
56     public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
57
58     //public static val DECIMAL = Types.typeForClass(Decimal);
59     public static val LONG = Types.typeForClass(Long);
60
61     val ClassPool classPool
62     val extension JavassistUtils utils;
63
64     CtClass BINDING_CODEC
65
66     CtClass ctQName
67
68     @Property
69     var File classFileCapturePath;
70
71     @Property
72     var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
73
74     @Property
75     var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
76
77     @Property
78     var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
79
80     @Property
81     var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
82
83     @Property
84     var GeneratorListener listener;
85
86     public new(ClassPool pool) {
87         classPool = pool;
88         utils = new JavassistUtils(pool)
89
90         BINDING_CODEC = BindingCodec.asCtClass;
91         ctQName = QName.asCtClass
92     }
93
94     def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
95         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
96             val ret = getGeneratedClass(inputType)
97             if (ret !== null) {
98                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
99             }
100             val ref = Types.typeForClass(inputType)
101             val node = typeToSchemaNode.get(ref)
102             val typeSpecBuilder = typeToDefinition.get(ref)
103             val typeSpec = typeSpecBuilder.toInstance();
104             val newret = generateTransformerFor(inputType, typeSpec, node);
105             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
106         ]
107     }
108
109     def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
110         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
111             val ret = getGeneratedClass(inputType)
112             if (ret !== null) {
113                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
114             }
115             val ref = Types.typeForClass(inputType)
116             val node = typeToAugmentation.get(ref)
117             val typeSpecBuilder = typeToDefinition.get(ref)
118             val typeSpec = typeSpecBuilder.toInstance();
119             val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
120             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
121         ]
122     }
123
124     def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
125         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
126             val ret = getGeneratedClass(inputType)
127             if (ret !== null) {
128                 return ret as Class<? extends BindingCodec<Object, Object>>;
129             }
130             val ref = Types.typeForClass(inputType)
131             val typeSpecBuilder = typeToDefinition.get(ref)
132             val typeSpec = typeSpecBuilder.toInstance();
133             val newret = generateCaseCodec(inputType, typeSpec, node);
134             return newret as Class<? extends BindingCodec<Object, Object>>;
135         ]
136     }
137
138     def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
139         return withClassLoaderAndLock(parentType.classLoader, lock) [ |
140             val inputName = parentType.name + "Key";
141             val inputType = loadClassWithTCCL(inputName);
142             val ret = getGeneratedClass(inputType)
143             if (ret !== null) {
144                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
145             }
146             val ref = Types.typeForClass(parentType)
147             val node = typeToSchemaNode.get(ref) as ListSchemaNode
148             val typeSpecBuilder = typeToDefinition.get(ref)
149             val typeSpec = typeSpecBuilder.identifierDefinition;
150             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
151             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
152         ]
153     }
154
155     def getIdentifierDefinition(GeneratedTypeBuilder builder) {
156         val inst = builder.toInstance
157         val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
158         return keyMethod.returnType as GeneratedTransferObject
159     }
160
161     def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
162         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
163             val ret = getGeneratedClass(inputType)
164             if (ret !== null) {
165                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
166             }
167             val ref = Types.typeForClass(inputType)
168             val node = typeToSchemaNode.get(ref) as ListSchemaNode
169             val typeSpecBuilder = typeToDefinition.get(ref)
170             val typeSpec = typeSpecBuilder.toInstance();
171             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
172             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
173         ]
174     }
175
176     private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
177         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
178             val transformer = getGeneratedClass(inputType)
179             if (transformer != null) {
180                 return transformer;
181             }
182             val newret = generateKeyTransformerFor(inputType, type, schema);
183             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
184         ]
185     }
186
187     private def Class getGeneratedClass(Class<? extends Object> cls) {
188
189         try {
190             return loadClassWithTCCL(cls.codecClassName)
191         } catch (ClassNotFoundException e) {
192             return null;
193         }
194     }
195
196     private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
197         val cls = loadClassWithTCCL(type.resolvedName + "Key");
198         keyTransformerFor(cls, type, node);
199     }
200
201     private def serializer(Type type) {
202         val cls = loadClassWithTCCL(type.resolvedName);
203
204         transformerFor(cls);
205
206     }
207
208     private def Class<?> getValueSerializer(GeneratedTransferObject type) {
209         val cls = loadClassWithTCCL(type.resolvedName);
210         val transformer = cls.generatedClass;
211         if (transformer !== null) {
212             return transformer;
213         }
214         val valueTransformer = generateValueTransformer(cls, type);
215         return valueTransformer;
216     }
217
218     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
219         try {
220             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
221             val properties = typeSpec.allProperties;
222             val ctCls = createClass(inputType.codecClassName) [
223                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
224                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
225                 staticQNameField(node.QName);
226                 implementsType(BINDING_CODEC)
227                 method(Object, "toDomStatic", QName, Object) [
228                     modifiers = PUBLIC + FINAL + STATIC
229                     body = '''
230                         {
231                             «QName.name» _resultName;
232                             if($1 != null) {
233                                 _resultName = «QName.name».create($1,QNAME.getLocalName());
234                             } else {
235                                 _resultName = QNAME;
236                             }
237                             java.util.List _childNodes = new java.util.ArrayList();
238                             «inputType.name» value = («inputType.name») $2;
239                             «FOR key : node.keyDefinition»
240                                 «val propertyName = key.getterName»
241                                 «val keyDef = node.getDataChildByName(key)»
242                                 «val property = properties.get(propertyName)»
243                                 «serializeProperty(keyDef, property, propertyName)»;
244                             «ENDFOR»
245                             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
246                         }
247                     '''
248                 ]
249                 method(Object, "fromDomStatic", QName, Object) [
250                     modifiers = PUBLIC + FINAL + STATIC
251                     body = '''
252                         {
253                             if($2 == null){
254                                 return  null;
255                             }
256                             «QName.name» _localQName = $1;
257                             java.util.Map _compositeNode = (java.util.Map) $2;
258                             «FOR key : node.keyDefinition»
259                                 «val propertyName = key.getterName»
260                                 «val keyDef = node.getDataChildByName(key)»
261                                 «val property = properties.get(propertyName)»
262                                 «deserializeProperty(keyDef, property, propertyName)»;
263                             «ENDFOR»
264                             «inputType.name» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
265                             return _value;
266                         }
267                     '''
268                 ]
269                 method(Object, "serialize", Object) [
270                     body = '''
271                         {
272                             java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
273                             «QName.name» _localQName = («QName.name») _input.getKey();
274                             «inputType.name» _keyValue = («inputType.name») _input.getValue();
275                             return toDomStatic(_localQName,_keyValue);
276                         }
277                     '''
278                 ]
279                 method(Object, "deserialize", Object) [
280                     body = '''
281                         return fromDomStatic(QNAME,$1);
282                     '''
283                 ]
284             ]
285             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
286             log.info("DOM Codec for {} was generated {}", inputType, ret)
287             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
288         } catch (Exception e) {
289             processException(inputType, e);
290             return null;
291         }
292     }
293
294     private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
295         ChoiceCaseNode node) {
296         try {
297             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
298             val ctCls = createClass(type.codecClassName) [
299                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
300                 implementsType(BINDING_CODEC)
301                 staticQNameField(inputType);
302                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
303                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
304                 method(Object, "toDomStatic", QName, Object) [
305                     modifiers = PUBLIC + FINAL + STATIC
306                     body = '''
307                         {
308                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
309                             java.util.List _childNodes = new java.util.ArrayList();
310                             «type.resolvedName» value = («type.resolvedName») $2;
311                             «transformDataContainerBody(type.allProperties, node)»
312                             return ($r) _childNodes;
313                         }
314                     '''
315                 ]
316                 method(Object, "serialize", Object) [
317                     body = '''
318                         {
319                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
320                             «QName.name» _localName = QNAME;
321                             if(_input.getKey() != null) {
322                                 _localName = («QName.name») _input.getKey();
323                             }
324                             return toDomStatic(_localName,_input.getValue());
325                         }
326                     '''
327                 ]
328                 method(Object, "fromDomStatic", QName, Object) [
329                     modifiers = PUBLIC + FINAL + STATIC
330                     body = deserializeBody(type, node)
331                 ]
332                 method(Object, "deserialize", Object) [
333                     body = '''
334                         {
335                             
336                             return fromDomStatic(QNAME,$1);
337                         }
338                     '''
339                 ]
340             ]
341
342             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
343             log.info("DOM Codec for {} was generated {}", inputType, ret)
344             return ret as Class<? extends BindingCodec<Object, Object>>;
345         } catch (Exception e) {
346             processException(inputType, e);
347             return null;
348         }
349     }
350
351     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
352         Class inputType, GeneratedType typeSpec, SchemaNode node) {
353         try {
354             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
355             val ctCls = createClass(typeSpec.codecClassName) [
356                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
357                 staticQNameField(inputType);
358                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
359                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
360                 implementsType(BINDING_CODEC)
361                 method(Object, "toDomStatic", QName, Object) [
362                     modifiers = PUBLIC + FINAL + STATIC
363                     body = serializeBodyFacade(typeSpec, node)
364                 ]
365                 method(Object, "serialize", Object) [
366                     body = '''
367                         {
368                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
369                             «QName.name» _localName = QNAME;
370                             if(_input.getKey() != null) {
371                                 _localName = («QName.name») _input.getKey();
372                             }
373                             return toDomStatic(_localName,_input.getValue());
374                         }
375                     '''
376                 ]
377                 method(Object, "fromDomStatic", QName, Object) [
378                     modifiers = PUBLIC + FINAL + STATIC
379                     body = deserializeBody(typeSpec, node)
380                 ]
381                 method(Object, "deserialize", Object) [
382                     body = '''
383                         return fromDomStatic(QNAME,$1);
384                     '''
385                 ]
386             ]
387
388             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
389             listener?.onDataContainerCodecCreated(inputType, ret);
390             log.info("DOM Codec for {} was generated {}", inputType, ret)
391             return ret;
392         } catch (Exception e) {
393             processException(inputType, e);
394             return null;
395         }
396     }
397
398     private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
399         Class inputType, GeneratedType type, AugmentationSchema node) {
400         try {
401             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
402             val properties = type.allProperties
403             val ctCls = createClass(type.codecClassName) [
404                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
405                 staticQNameField(inputType);
406                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
407                 staticField(it, AUGMENTATION_CODEC, BindingCodec)
408                 implementsType(BINDING_CODEC)
409                 method(Object, "toDomStatic", QName, Object) [
410                     modifiers = PUBLIC + FINAL + STATIC
411                     body = '''
412                         {
413                             //System.out.println("Qname " + $1);
414                             //System.out.println("Value " + $2);
415                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
416                             java.util.List _childNodes = new java.util.ArrayList();
417                             «type.resolvedName» value = («type.resolvedName») $2;
418                             «FOR child : node.childNodes»
419                                 «var signature = properties.getFor(child)»
420                                 //System.out.println("«signature.key»" + value.«signature.key»());
421                                 «serializeProperty(child, signature.value, signature.key)»
422                             «ENDFOR»
423                             return ($r) _childNodes;
424                         }
425                     '''
426                 ]
427                 method(Object, "serialize", Object) [
428                     body = '''
429                         {
430                         java.util.Map.Entry _input = (java.util.Map.Entry) $1;
431                         «QName.name» _localName = QNAME;
432                         if(_input.getKey() != null) {
433                             _localName = («QName.name») _input.getKey();
434                         }
435                         return toDomStatic(_localName,_input.getValue());
436                         }
437                     '''
438                 ]
439                 method(Object, "fromDomStatic", QName, Object) [
440                     modifiers = PUBLIC + FINAL + STATIC
441                     body = '''
442                         {
443                             «QName.name» _localQName = QNAME;
444                             
445                             if($2 == null) {
446                             return null;
447                             }
448                             java.util.Map _compositeNode = (java.util.Map) $2;
449                             ////System.out.println(_localQName + " " + _compositeNode);
450                             «type.builderName» _builder = new «type.builderName»();
451                             «FOR child : node.childNodes»
452                                 «val signature = properties.getFor(child)»
453                                 «deserializeProperty(child, signature.value, signature.key)»
454                                 
455                                 _builder.«signature.key.toSetter»(«signature.key»);
456                             «ENDFOR»
457                             return _builder.build();
458                         }
459                     '''
460                 ]
461                 method(Object, "deserialize", Object) [
462                     body = '''
463                         return fromDomStatic(QNAME,$1);
464                     '''
465                 ]
466             ]
467
468             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
469             listener?.onDataContainerCodecCreated(inputType, ret);
470             return ret;
471         } catch (Exception e) {
472             processException(inputType, e);
473             return null;
474         }
475     }
476
477     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
478         Class inputType, GeneratedType typeSpec, ChoiceNode node) {
479         try {
480             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
481             val ctCls = createClass(typeSpec.codecClassName) [
482                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
483                 //staticQNameField(inputType);
484                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
485                 staticField(it, CLASS_TO_CASE_MAP, Map)
486                 staticField(it, COMPOSITE_TO_CASE, Map)
487                 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
488                 implementsType(BINDING_CODEC)
489                 method(List, "toDomStatic", QName, Object) [
490                     modifiers = PUBLIC + FINAL + STATIC
491                     body = '''
492                         {
493                             if($2 == null) {
494                                 return null;
495                             }
496                             «DataObject.name» _baValue = («DataObject.name») $2;
497                             Class _baClass = _baValue.getImplementedInterface();
498                             «BINDING_CODEC.name» _codec =  «CLASS_TO_CASE_MAP».get(_baClass);
499                             if(_codec == null) {
500                                 return null;
501                             }
502                             java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
503                             return (java.util.List) _codec.serialize(_input);
504                         }
505                     '''
506                 ]
507                 method(Object, "serialize", Object) [
508                     body = '''
509                         throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
510                     '''
511                 ]
512                 method(Object, "fromDomStatic", QName, Map) [
513                     modifiers = PUBLIC + FINAL + STATIC
514                     body = '''
515                         {
516                             «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
517                             if(_codec != null) {
518                                 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
519                             }
520                             return null;
521                         }
522                     '''
523                 ]
524                 method(Object, "deserialize", Object) [
525                     body = '''
526                         throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
527                     '''
528                 ]
529             ]
530
531             val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
532             val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
533             listener?.onChoiceCodecCreated(inputType, ret);
534             log.info("DOM Codec for {} was generated {}", inputType, ret)
535             return ret;
536         } catch (Exception e) {
537             processException(inputType, e);
538             return null;
539         }
540     }
541
542     private def keyConstructorList(List<QName> qnames) {
543         val names = new TreeSet<String>()
544         for (name : qnames) {
545             val fieldName = name.getterName;
546             names.add(fieldName);
547         }
548         return Joiner.on(",").join(names);
549     }
550
551     private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
552         val ret = serializeBody(type, node);
553         return ret;
554     }
555
556     private def String deserializeBody(GeneratedType type, SchemaNode node) {
557         val ret = deserializeBodyImpl(type, node);
558         return ret;
559     }
560
561     private def deserializeKey(GeneratedType type, ListSchemaNode node) {
562         if (node.keyDefinition != null && !node.keyDefinition.empty) {
563             return '''
564                 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
565                 _builder.setKey(getKey);
566             ''';
567         }
568     }
569
570     private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
571         {
572             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
573             
574             if($2 == null) {
575                 return null;
576             }
577             java.util.Map _compositeNode = (java.util.Map) $2;
578             «type.builderName» _builder = new «type.builderName»();
579             return _builder.build();
580         }
581     '''
582
583     private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
584         {
585             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
586             if($2 == null) {
587                 return null;
588             }
589             java.util.Map _compositeNode = (java.util.Map) $2;
590             «type.builderName» _builder = new «type.builderName»();
591             «deserializeKey(type, node)»
592             «deserializeDataNodeContainerBody(type, node)»
593             «deserializeAugmentations»
594             return _builder.build();
595         }
596     '''
597
598     private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
599         {
600             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
601             if($2 == null) {
602                 return null;
603             }
604             java.util.Map _compositeNode = (java.util.Map) $2;
605             «type.builderName» _builder = new «type.builderName»();
606             «deserializeDataNodeContainerBody(type, node)»
607             «deserializeAugmentations»
608             return _builder.build();
609         }
610     '''
611
612     private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
613         {
614             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
615             
616             if($2 == null) {
617                 return null;
618             }
619             java.util.Map _compositeNode = (java.util.Map) $2;
620             ////System.out.println(_localQName + " " + _compositeNode);
621             «type.builderName» _builder = new «type.builderName»();
622             «deserializeDataNodeContainerBody(type, node)»
623             «deserializeAugmentations»
624             return _builder.build();
625         }
626     '''
627
628     private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
629         deserializeNodeContainerBodyImpl(type, type.allProperties, node);
630     }
631
632     private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
633         DataNodeContainer node) {
634         val ret = '''
635             «FOR child : node.childNodes.filter[!augmenting]»
636                 «val signature = properties.getFor(child)»
637                 «deserializeProperty(child, signature.value, signature.key)»
638                 
639                 _builder.«signature.key.toSetter»(«signature.key»);
640             «ENDFOR»
641         '''
642         return ret;
643     }
644
645     def deserializeAugmentations() '''
646         java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
647         if(_augmentation != null) {
648             «Iterator.name» _entries = _augmentation.entrySet().iterator();
649             while(_entries.hasNext()) {
650                 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
651                 //System.out.println("Aug. key:" + _entry.getKey());
652                 Class _type = (Class) _entry.getKey();
653                 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
654                 _builder.addAugmentation(_type,_value);
655             }
656         }
657     '''
658
659     private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
660         String propertyName) '''
661         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
662             localName»"));
663         ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
664         java.util.List «propertyName» = new java.util.ArrayList();
665         if(_dom_«propertyName» != null) {
666             java.util.List _serialized = new java.util.ArrayList();
667             java.util.Iterator _iterator = _dom_«propertyName».iterator();
668             boolean _hasNext = _iterator.hasNext();
669             while(_hasNext) {
670                 Object _listItem = _iterator.next();
671                 ////System.out.println("  item" + _listItem);
672                 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
673                 ////System.out.println("  value" + _value);
674                 «propertyName».add(_value);
675                 _hasNext = _iterator.hasNext();
676             }
677         }
678         
679         ////System.out.println(" list" + «propertyName»);
680     '''
681
682     private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
683         String propertyName) '''
684         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
685             localName»"));
686         java.util.List «propertyName» = new java.util.ArrayList();
687         if(_dom_«propertyName» != null) {
688             java.util.List _serialized = new java.util.ArrayList();
689             java.util.Iterator _iterator = _dom_«propertyName».iterator();
690             boolean _hasNext = _iterator.hasNext();
691             while(_hasNext) {
692                 Object _listItem = _iterator.next();
693                 if(_listItem instanceof java.util.Map.Entry) {
694                     Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
695                     Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
696                     «propertyName».add(_value);
697                 }
698                 _hasNext = _iterator.hasNext();
699             }
700         }
701     '''
702
703     private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
704         java.util.List _dom_«propertyName»_list = 
705             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
706         «type.resolvedName» «propertyName» = null;
707         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
708             java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
709             Object _inner_value = _dom_«propertyName».getValue();
710             «propertyName» = «deserializeValue(type, "_inner_value")»;
711         }
712     '''
713
714     private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
715         String propertyName) '''
716         java.util.List _dom_«propertyName»_list = 
717             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
718         «type.resolvedName» «propertyName» = null;
719         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
720             
721             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
722             «propertyName» =  «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
723         }
724     '''
725
726     private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
727         «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
728     '''
729
730     private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
731         («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
732     '''
733
734     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
735         Class<?> inputType, GeneratedTransferObject typeSpec) {
736         try {
737
738             val returnType = typeSpec.valueReturnType;
739             if (returnType == null) {
740
741                 val ctCls = createDummyImplementation(inputType, typeSpec);
742                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
743                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
744             }
745             val ctCls = createClass(typeSpec.codecClassName) [
746                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
747                 implementsType(BINDING_CODEC)
748                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
749                 implementsType(BindingDeserializer.asCtClass)
750                 method(Object, "toDomValue", Object) [
751                     modifiers = PUBLIC + FINAL + STATIC
752                     body = '''
753                         {
754                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
755                             
756                             if($1 == null) {
757                                 return null;
758                             }
759                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
760                             ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
761                             «returnType.resolvedName» _value =  _encapsulatedValue.getValue();
762                             ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
763                             Object _domValue = «serializeValue(returnType, "_value")»;
764                             return _domValue;
765                         }
766                     '''
767                 ]
768                 method(Object, "serialize", Object) [
769                     body = '''
770                         {
771                             return toDomValue($1);
772                         }
773                     '''
774                 ]
775                 method(Object, "fromDomValue", Object) [
776                     modifiers = PUBLIC + FINAL + STATIC
777                     body = '''
778                         {
779                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
780                             
781                             if($1 == null) {
782                                 return null;
783                             }
784                             «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
785                             «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
786                             return _value;
787                         }
788                     '''
789                 ]
790                 method(Object, "deserialize", Object) [
791                     body = '''{
792                             return fromDomValue($1);
793                     }
794                     '''
795                 ]
796             ]
797
798             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
799             log.info("DOM Codec for {} was generated {}", inputType, ret)
800             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
801         } catch (Exception e) {
802             log.error("Cannot compile DOM Codec for {}", inputType, e);
803             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
804             exception.addSuppressed(e);
805             throw exception;
806         }
807
808     }
809
810     private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
811         log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
812         return createClass(typeSpec.codecClassName) [
813             //staticField(Map,"AUGMENTATION_SERIALIZERS");
814             implementsType(BINDING_CODEC)
815             implementsType(BindingDeserializer.asCtClass)
816             method(Object, "toDomValue", Object) [
817                 modifiers = PUBLIC + FINAL + STATIC
818                 body = '''return null;'''
819             ]
820             method(Object, "serialize", Object) [
821                 body = '''
822                     {
823                         return toDomValue($1);
824                     }
825                 '''
826             ]
827             method(Object, "fromDomValue", Object) [
828                 modifiers = PUBLIC + FINAL + STATIC
829                 body = '''return null;'''
830             ]
831             method(Object, "deserialize", Object) [
832                 body = '''{
833                         return fromDomValue($1);
834                     }
835                     '''
836             ]
837         ]
838     }
839
840     private def Type getValueReturnType(GeneratedTransferObject object) {
841         for (prop : object.properties) {
842             if (prop.name == "value") {
843                 return prop.returnType;
844             }
845         }
846         if (object.superType != null) {
847             return getValueReturnType(object.superType);
848         }
849         return null;
850     }
851
852     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
853         Class<?> inputType, Enumeration typeSpec) {
854         try {
855             log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
856             val ctCls = createClass(typeSpec.codecClassName) [
857                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
858                 implementsType(BINDING_CODEC)
859                 method(Object, "toDomValue", Object) [
860                     modifiers = PUBLIC + FINAL + STATIC
861                     body = '''
862                         if($1 == null) {
863                             return null;
864                         }
865                         «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
866                         return _value.getValue();
867                     '''
868                 ]
869                 method(Object, "serialize", Object) [
870                     body = '''
871                         return toDomValue($1);
872                     '''
873                 ]
874                 method(Object, "fromDomValue", Object) [
875                     modifiers = PUBLIC + FINAL + STATIC
876                     body = '''
877                         if($1 == null) {
878                             return null;
879                         }
880                         _simpleValue = null;
881                         «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
882                         return _value;
883                     '''
884                 ]
885                 method(Object, "deserialize", Object) [
886                     body = '''
887                         return fromDomValue($1);
888                     '''
889                 ]
890             ]
891
892             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
893             log.info("DOM Codec for {} was generated {}", inputType, ret)
894             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
895         } catch (CodeGenerationException e) {
896             throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
897         } catch (Exception e) {
898             log.error("Cannot compile DOM Codec for {}", inputType, e);
899             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
900             exception.addSuppressed(e);
901             throw exception;
902         }
903
904     }
905
906     def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
907         val cls = newClass.toClass(loader, domain);
908         if (classFileCapturePath !== null) {
909             newClass.writeFile(classFileCapturePath.absolutePath);
910         }
911         listener?.onCodecCreated(cls);
912         return cls;
913     }
914
915     def debugWriteClass(CtClass class1) {
916         val path = class1.name.replace(".", "/") + ".class"
917
918         val captureFile = new File(classFileCapturePath, path);
919         captureFile.createNewFile
920
921     }
922
923     private def dispatch String deserializeValue(Type type, String domParameter) {
924         if (INSTANCE_IDENTIFIER.equals(type)) {
925
926             return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
927         }
928
929         return '''(«type.resolvedName») «domParameter»'''
930
931     }
932
933     /** 
934      * Default catch all
935      * 
936      **/
937     private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
938         «type.resolvedName» «propertyName» = null;
939     '''
940
941     private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
942         String propertyName) {
943         _deserializeProperty(container, type.toInstance, propertyName)
944     }
945
946     public static def toSetter(String it) {
947
948         if (startsWith("is")) {
949             return "set" + substring(2);
950         } else if (startsWith("get")) {
951             return "set" + substring(3);
952         }
953         return "set" + it;
954     }
955
956     /* 
957     private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
958         «type.resolvedName» «propertyName» = value.«propertyName»();
959         if(«propertyName» != null) {
960             Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
961             _childNodes.add(domValue);
962         }
963     '''
964     */
965     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
966
967     private def staticQNameField(CtClass it, Class<?> node) {
968         val field = new CtField(ctQName, "QNAME", it);
969         field.modifiers = PUBLIC + FINAL + STATIC;
970         addField(field, '''«node.name».QNAME''')
971     }
972
973     private def staticQNameField(CtClass it, QName node) {
974         val field = new CtField(ctQName, "QNAME", it);
975         field.modifiers = PUBLIC + FINAL + STATIC;
976         addField(field,
977             '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
978     }
979
980     private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
981         {
982             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
983             java.util.List _childNodes = new java.util.ArrayList();
984             «type.resolvedName» value = («type.resolvedName») $2;
985             «transformDataContainerBody(type.allProperties, node)»
986             «serializeAugmentations»
987             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
988         }
989     '''
990
991     private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
992         {
993             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
994             java.util.List _childNodes = new java.util.ArrayList();
995             «type.resolvedName» value = («type.resolvedName») $2;
996             «transformDataContainerBody(type.allProperties, node)»
997             «serializeAugmentations»
998             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
999         }
1000     '''
1001
1002     private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1003         {
1004         «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1005             java.util.List _childNodes = new java.util.ArrayList();
1006             «type.resolvedName» value = («type.resolvedName») $2;
1007             «transformDataContainerBody(type.allProperties, node)»
1008             «serializeAugmentations»
1009             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1010         }
1011     '''
1012
1013     private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1014         {
1015         «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1016             java.util.List _childNodes = new java.util.ArrayList();
1017             «type.resolvedName» value = («type.resolvedName») $2;
1018             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1019         }
1020     '''
1021
1022     private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
1023         val ret = '''
1024             «FOR child : node.childNodes.filter[!augmenting]»
1025                 «var signature = properties.getFor(child)»
1026                 //System.out.println("«signature.key»" + value.«signature.key»());
1027                 «serializeProperty(child, signature.value, signature.key)»
1028             «ENDFOR»
1029         '''
1030         return ret;
1031     }
1032
1033     def serializeAugmentations() '''
1034         java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1035         if(_augmentations != null) {
1036             _childNodes.addAll(_augmentations);
1037         }
1038     '''
1039
1040     def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1041         val sig = map.get(node.getterName);
1042         if (sig == null) {
1043
1044             return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1045         }
1046         return new SimpleEntry(node.getterName, sig);
1047     }
1048
1049     private static def String getBooleanGetterName(DataSchemaNode node) {
1050         return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1051     }
1052
1053     private static def String getGetterName(DataSchemaNode node) {
1054         return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1055     }
1056
1057     private static def String getGetterName(QName node) {
1058         return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1059     }
1060
1061     private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1062         String propertyName) '''
1063         «type.resolvedName» «propertyName» = value.«propertyName»();
1064         if(«propertyName» != null) {
1065             java.util.Iterator _iterator = «propertyName».iterator();
1066             boolean _hasNext = _iterator.hasNext();
1067             while(_hasNext) {
1068                 Object _listItem = _iterator.next();
1069                 Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
1070                 _childNodes.add(_domValue);
1071                 _hasNext = _iterator.hasNext();
1072             }
1073         }
1074     '''
1075
1076     private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1077         «type.resolvedName» «propertyName» = value.«propertyName»();
1078         
1079         if(«propertyName» != null) {
1080             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1081             Object _propValue = «serializeValue(type, propertyName)»;
1082             if(_propValue != null) {
1083                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1084                 _childNodes.add(_domValue);
1085             }
1086         }
1087     '''
1088
1089     private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1090         resolvedName».toDomValue(«parameter»)'''
1091
1092     private def dispatch serializeValue(Type signature, String property) {
1093         if (INSTANCE_IDENTIFIER == signature) {
1094             return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1095         }
1096         return '''«property»''';
1097     }
1098
1099     private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1100         String propertyName) '''
1101         «type.resolvedName» «propertyName» = value.«propertyName»();
1102         if(«propertyName» != null) {
1103             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1104             java.util.Iterator _iterator = «propertyName».iterator();
1105             boolean _hasNext = _iterator.hasNext();
1106             while(_hasNext) {
1107                 Object _listItem = _iterator.next();
1108                 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1109                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1110                 _childNodes.add(_domValue);
1111                 _hasNext = _iterator.hasNext();
1112             }
1113         }
1114     '''
1115
1116     private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1117         String propertyName) '''
1118         «type.resolvedName» «propertyName» = value.«propertyName»();
1119         if(«propertyName» != null) {
1120             java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1121             _childNodes.addAll(domValue);
1122         }
1123     '''
1124
1125     /** 
1126      * Default catch all
1127      * 
1128      **/
1129     private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1130         «type.resolvedName» «propertyName» = value.«propertyName»();
1131         if(«propertyName» != null) {
1132             Object domValue = «propertyName»;
1133             _childNodes.add(domValue);
1134         }
1135     '''
1136
1137     private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1138         String propertyName) {
1139         serializeProperty(container, type.toInstance, propertyName)
1140     }
1141
1142     private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1143         String propertyName) '''
1144         «type.resolvedName» «propertyName» = value.«propertyName»();
1145         if(«propertyName» != null) {
1146             Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1147             _childNodes.add(domValue);
1148         }
1149     '''
1150
1151     private def codecClassName(GeneratedType typeSpec) {
1152         return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1153     }
1154
1155     private def codecClassName(Class typeSpec) {
1156         return '''«typeSpec.name»$Broker$Codec$DOM'''
1157     }
1158
1159     private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
1160         val ret = new HashMap<String, Type>();
1161         type.collectAllProperties(ret);
1162         return ret;
1163     }
1164
1165     private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1166         for (definition : type.methodDefinitions) {
1167             set.put(definition.name, definition.returnType);
1168         }
1169         for (property : type.properties) {
1170             set.put(property.getterName, property.returnType);
1171         }
1172         for (parent : type.implements) {
1173             parent.collectAllProperties(set);
1174         }
1175     }
1176
1177     def String getGetterName(GeneratedProperty property) {
1178         return "get" + property.name.toFirstUpper
1179     }
1180
1181     private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1182         // NOOP for generic type.
1183     }
1184
1185     def String getResolvedName(Type type) {
1186         return type.asCtClass.name;
1187     }
1188
1189     def String getResolvedName(Class type) {
1190         return type.asCtClass.name;
1191     }
1192
1193     def CtClass asCtClass(Type type) {
1194         val name = type.fullyQualifiedName
1195         val cls = loadClassWithTCCL(type.fullyQualifiedName)
1196         return cls.asCtClass;
1197     }
1198
1199     private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1200         log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1201         throw e;
1202     }
1203
1204     private def dispatch processException(Class<?> inputType, Exception e) {
1205         log.error("Cannot compile DOM Codec for {}", inputType, e);
1206         val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1207         throw exception;
1208     }
1209
1210 }
1211
1212 @Data
1213 class PropertyPair {
1214
1215     String getterName;
1216
1217     Type type;
1218
1219     @Property
1220     Type returnType;
1221     @Property
1222     SchemaNode schemaNode;
1223 }