Merge "BUG-1276: fixed generated union constructor"
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / TransformerGenerator.xtend
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.sal.binding.generator.impl
9
10 import com.google.common.base.Joiner
11 import java.io.File
12 import java.security.ProtectionDomain
13 import java.util.AbstractMap.SimpleEntry
14 import java.util.Collection
15 import java.util.Collections
16 import java.util.HashMap
17 import java.util.HashSet
18 import java.util.Iterator
19 import java.util.List
20 import java.util.Map
21 import java.util.Map.Entry
22 import java.util.Set
23 import java.util.TreeSet
24 import javassist.CannotCompileException
25 import javassist.ClassPool
26 import javassist.CtClass
27 import javassist.CtField
28 import javassist.CtMethod
29 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
30 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
31 import org.opendaylight.yangtools.binding.generator.util.Types
32 import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils
33 import org.opendaylight.yangtools.sal.binding.generator.util.CodeGenerationException
34 import org.opendaylight.yangtools.sal.binding.generator.util.XtendHelper
35 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
36 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
37 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
38 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
39 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
40 import org.opendaylight.yangtools.sal.binding.model.api.Type
41 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
42 import org.opendaylight.yangtools.yang.binding.Augmentation
43 import org.opendaylight.yangtools.yang.binding.BindingCodec
44 import org.opendaylight.yangtools.yang.binding.BindingDeserializer
45 import org.opendaylight.yangtools.yang.binding.BindingMapping
46 import org.opendaylight.yangtools.yang.binding.DataObject
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
48 import org.opendaylight.yangtools.yang.common.QName
49 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
50 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
51 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
52 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
53 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
54 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
55 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
56 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
57 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
58 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
59 import org.opendaylight.yangtools.yang.model.api.SchemaNode
60 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
61 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
62 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit
63 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition
64 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition
65 import org.opendaylight.yangtools.yang.model.util.EnumerationType
66 import org.opendaylight.yangtools.yang.model.util.ExtendedType
67 import org.slf4j.LoggerFactory
68
69 import static com.google.common.base.Preconditions.*
70 import static javassist.Modifier.*
71 import static org.opendaylight.yangtools.sal.binding.generator.impl.CodecMapping.*
72
73 import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.*
74 import java.util.ArrayList
75 import org.opendaylight.yangtools.sal.binding.generator.util.DefaultSourceCodeGenerator
76 import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGeneratorFactory
77 import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGenerator
78
79 class TransformerGenerator extends AbstractTransformerGenerator {
80     private static val LOG = LoggerFactory.getLogger(TransformerGenerator)
81
82     public static val STRING = Types.typeForClass(String);
83     public static val BOOLEAN = Types.typeForClass(Boolean);
84     public static val INTEGER = Types.typeForClass(Integer);
85     public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier);
86     //public static val DECIMAL = Types.typeForClass(Decimal);
87     public static val LONG = Types.typeForClass(Long);
88     public static val CLASS_TYPE = Types.typeForClass(Class);
89
90     @Property
91     var File classFileCapturePath;
92
93     val CtClass BINDING_CODEC
94     val CtClass ctQName
95
96     val SourceCodeGeneratorFactory sourceCodeGeneratorFactory = new SourceCodeGeneratorFactory();
97
98     public new(TypeResolver typeResolver, ClassPool pool) {
99         super(typeResolver, pool)
100
101         BINDING_CODEC = BindingCodec.asCtClass;
102         ctQName = QName.asCtClass
103     }
104
105     override transformerForImpl(Class inputType) {
106         return runOnClassLoader(inputType.classLoader) [ |
107             val ret = getGeneratedClass(inputType)
108             if (ret !== null) {
109                 listener.onClassProcessed(inputType);
110                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
111             }
112             val ref = Types.typeForClass(inputType)
113             val node = getSchemaNode(ref)
114             createMapping(inputType, node, null)
115             val typeSpecBuilder = getDefinition(ref)
116             checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
117             val typeSpec = typeSpecBuilder.toInstance();
118             val newret = generateTransformerFor(inputType, typeSpec, node);
119             listener.onClassProcessed(inputType);
120             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
121         ]
122     }
123
124     def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
125         return runOnClassLoader(inputType.classLoader) [ |
126             createMapping(inputType, node, null)
127             val ret = getGeneratedClass(inputType)
128             if (ret !== null) {
129                 listener.onClassProcessed(inputType);
130                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
131             }
132             val ref = Types.typeForClass(inputType)
133             var typeSpecBuilder = getDefinition(ref)
134             if (typeSpecBuilder == null) {
135                 typeSpecBuilder = getTypeBuilder(node.path);
136             }
137
138             checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
139             val typeSpec = typeSpecBuilder.toInstance();
140             val newret = generateTransformerFor(inputType, typeSpec, node);
141             listener.onClassProcessed(inputType);
142             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
143         ]
144     }
145
146     override augmentationTransformerForImpl(Class inputType) {
147         return runOnClassLoader(inputType.classLoader) [ |
148
149             val ret = getGeneratedClass(inputType)
150             if (ret !== null) {
151                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
152             }
153             val ref = Types.typeForClass(inputType)
154             val node = getAugmentation(ref)
155             val typeSpecBuilder = getDefinition(ref)
156             val typeSpec = typeSpecBuilder.toInstance();
157             //mappingForNodes(node.childNodes, typeSpec.allProperties, bindingId)
158             val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
159             listener.onClassProcessed(inputType);
160             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
161         ]
162     }
163
164     override caseCodecForImpl(Class inputType, ChoiceCaseNode node) {
165         return runOnClassLoader(inputType.classLoader) [ |
166             createMapping(inputType, node, null)
167             val ret = getGeneratedClass(inputType)
168             if (ret !== null) {
169                 return ret as Class<? extends BindingCodec<Object, Object>>;
170             }
171             val ref = Types.typeForClass(inputType)
172             val typeSpecBuilder = getDefinition(ref)
173             val typeSpec = typeSpecBuilder.toInstance();
174             val newret = generateCaseCodec(inputType, typeSpec, node);
175             return newret as Class<? extends BindingCodec<Object, Object>>;
176         ]
177     }
178
179     override keyTransformerForIdentifiableImpl(Class parentType) {
180         return runOnClassLoader(parentType.classLoader) [ |
181             val inputName = parentType.name + "Key";
182             val inputType = loadClass(inputName);
183             val ret = getGeneratedClass(inputType)
184             if (ret !== null) {
185                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
186             }
187             val ref = Types.typeForClass(parentType)
188             val node = getSchemaNode(ref) as ListSchemaNode
189             val typeSpecBuilder = getDefinition(ref)
190             val typeSpec = typeSpecBuilder.identifierDefinition;
191             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
192             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
193         ]
194     }
195
196     private def void createMapping(Class<?> inputType, SchemaNode node, InstanceIdentifier<?> parentId) {
197         var ClassLoader cl = inputType.classLoader
198         if (cl === null) {
199             cl = Thread.currentThread.contextClassLoader
200         }
201         ClassLoaderUtils.withClassLoader(cl,
202             [ |
203                 if (!(node instanceof DataNodeContainer)) {
204                     return null
205                 }
206                 var InstanceIdentifier<?> bindingId = getBindingIdentifierByPath(node.path)
207                 if (bindingId != null) {
208                     return null
209                 }
210                 val ref = Types.typeForClass(inputType)
211                 var typeSpecBuilder = getDefinition(ref)
212                 if (typeSpecBuilder == null) {
213                     typeSpecBuilder = getTypeBuilder(node.path);
214                 }
215                 checkState(typeSpecBuilder !== null, "Could not find type definition for %s, $s", inputType.name, node);
216                 val typeSpec = typeSpecBuilder.toInstance();
217                 var InstanceIdentifier<?> parent
218                 if (parentId == null) {
219                     bindingId = InstanceIdentifier.create(inputType as Class)
220                     parent = bindingId
221                     putPathToBindingIdentifier(node.path, bindingId)
222                 } else {
223                     parent = putPathToBindingIdentifier(node.path, parentId, inputType)
224                 }
225                 val Map<String, Type> properties = typeSpec.allProperties
226                 if (node instanceof DataNodeContainer) {
227                     mappingForNodes((node as DataNodeContainer).childNodes, properties, parent)
228                 } else if (node instanceof ChoiceNode) {
229                     mappingForNodes((node as ChoiceNode).cases, properties, parent)
230                 }
231                 return null;
232             ])
233     }
234
235     private def void mappingForNodes(Collection<? extends DataSchemaNode> childNodes, Map<String, Type> properties,
236         InstanceIdentifier<?> parent) {
237         for (DataSchemaNode child : childNodes) {
238             val signature = properties.getFor(child)
239             if (signature != null) {
240                 val Type childType = signature.value
241                 var Class<?> childTypeClass = null;
242                 if (child instanceof ListSchemaNode && childType instanceof ParameterizedType) {
243                     childTypeClass = loadClass((childType as ParameterizedType).actualTypeArguments.get(0))
244                 } else {
245                     childTypeClass = loadClass(childType)
246                 }
247                 createMapping(childTypeClass, child, parent)
248             }
249         }
250     }
251
252     def getIdentifierDefinition(GeneratedTypeBuilder builder) {
253         val inst = builder.toInstance
254         val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
255         return keyMethod.returnType as GeneratedTransferObject
256     }
257
258     override keyTransformerForIdentifierImpl(Class inputType) {
259         return runOnClassLoader(inputType.classLoader) [ |
260             val ret = getGeneratedClass(inputType)
261             if (ret !== null) {
262                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
263             }
264             val ref = Types.typeForClass(inputType)
265             val node = getSchemaNode(ref) as ListSchemaNode
266             val typeSpecBuilder = getDefinition(ref)
267             val typeSpec = typeSpecBuilder.toInstance();
268             val newret = generateKeyTransformerFor(inputType, typeSpec, node);
269             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
270         ]
271     }
272
273     private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
274         return runOnClassLoader(inputType.classLoader) [ |
275             val transformer = getGeneratedClass(inputType)
276             if (transformer != null) {
277                 return transformer;
278             }
279             val newret = generateKeyTransformerFor(inputType, type, schema);
280             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
281         ]
282     }
283
284     private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
285
286         try {
287             return loadClass(cls.codecClassName)
288         } catch (ClassNotFoundException e) {
289             return null;
290         }
291     }
292
293     private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
294         val cls = loadClass(type.resolvedName + "Key");
295         keyTransformerFor(cls, type, node);
296     }
297
298     private def serializer(Type type, DataSchemaNode node) {
299         val cls = loadClass(type.resolvedName);
300         transformerFor(cls, node);
301     }
302
303     private def Class<?> valueSerializer(GeneratedTransferObject type, TypeDefinition<?> typeDefinition) {
304         val cls = loadClass(type.resolvedName);
305         val transformer = cls.generatedClass;
306         if (transformer !== null) {
307             return transformer;
308         }
309         var baseType = typeDefinition;
310         while (baseType.baseType != null) {
311             baseType = baseType.baseType;
312         }
313         val finalType = baseType;
314         return runOnClassLoader(cls.classLoader) [ |
315             val valueTransformer = generateValueTransformer(cls, type, finalType);
316             return valueTransformer;
317         ]
318     }
319
320     private def Class<?> valueSerializer(Enumeration type, TypeDefinition<?> typeDefinition) {
321         val cls = loadClass(type.resolvedName);
322         val transformer = cls.generatedClass;
323         if (transformer !== null) {
324             return transformer;
325         }
326
327         return runOnClassLoader(cls.classLoader) [ |
328             val valueTransformer = generateValueTransformer(cls, type, typeDefinition);
329             return valueTransformer;
330         ]
331     }
332
333     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
334         try {
335
336             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
337
338             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
339             val properties = typeSpec.allProperties;
340             val ctCls = createClass(inputType.codecClassName) [
341                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
342                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
343                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
344                 staticQNameField(node.QName, sourceGenerator);
345                 implementsType(BINDING_CODEC)
346                 method(Object, "toDomStatic", #[QName, Object]) [
347                     modifiers = PUBLIC + FINAL + STATIC
348                     val body = '''
349                         {
350                             «QName.name» _resultName;
351                             if($1 != null) {
352                                 _resultName = «QName.name».create($1,QNAME.getLocalName());
353                             } else {
354                                 _resultName = QNAME;
355                             }
356                             java.util.List _childNodes = new java.util.ArrayList();
357                             «inputType.resolvedName» value = («inputType.name») $2;
358                             «FOR key : node.keyDefinition»
359                                 «val propertyName = key.getterName»
360                                 «val keyDef = node.getDataChildByName(key)»
361                                 «val property = properties.get(propertyName)»
362                                 «serializeProperty(keyDef, property, propertyName)»;
363                             «ENDFOR»
364                             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
365                         }
366                     '''
367                     setBodyChecked(body, sourceGenerator)
368                 ]
369                 method(Object, "fromDomStatic", #[QName, Object]) [
370                     modifiers = PUBLIC + FINAL + STATIC
371                     val body = '''
372                         {
373                             if($2 == null){
374                                 return  null;
375                             }
376                             «QName.name» _localQName = $1;
377                             java.util.Map _compositeNode = (java.util.Map) $2;
378                             boolean _is_empty = true;
379                             «FOR key : node.keyDefinition»
380                                 «val propertyName = key.getterName»
381                                 «val keyDef = node.getDataChildByName(key)»
382                                 «val property = properties.get(propertyName)»
383                                 «deserializeProperty(keyDef, property, propertyName)»;
384                             «ENDFOR»
385                             «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
386                             keyConstructorList»);
387                             return _value;
388                         }
389                     '''
390                     setBodyChecked(body, sourceGenerator)
391                 ]
392                 method(Object, "serialize", Object) [
393                     val body = '''
394                         {
395                             java.util.Map.Entry _input =  (java.util.Map.Entry) $1;
396                             «QName.name» _localQName = («QName.name») _input.getKey();
397                             «inputType.name» _keyValue = («inputType.name») _input.getValue();
398                             return toDomStatic(_localQName,_keyValue);
399                         }
400                     '''
401                     setBodyChecked(body, sourceGenerator)
402                 ]
403                 method(Object, "deserialize", Object) [
404                     val body = '''
405                         {
406                             «QName.name» _qname = QNAME;
407                             if($1 instanceof java.util.Map.Entry) {
408                                 _qname = («QName.name») ((java.util.Map.Entry) $1).getKey();
409                             }
410                             return fromDomStatic(_qname,$1);
411                         }
412                     '''
413                     setBodyChecked(body, sourceGenerator)
414                 ]
415             ]
416             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
417             sourceGenerator.outputGeneratedSource( ctCls )
418             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
419             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
420         } catch (Exception e) {
421             processException(inputType, e);
422             return null;
423         }
424     }
425
426     private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
427         ChoiceCaseNode node) {
428         try {
429             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
430
431             //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
432             val ctCls = createClass(type.codecClassName) [
433                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
434                 implementsType(BINDING_CODEC)
435                 staticQNameField(node.QName, sourceGenerator);
436                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
437                 staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
438                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
439                 method(Object, "toDomStatic", #[QName, Object]) [
440                     modifiers = PUBLIC + FINAL + STATIC
441                     val body = '''
442                         {
443                             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
444                             java.util.List _childNodes = new java.util.ArrayList();
445                             «type.resolvedName» value = («type.resolvedName») $2;
446                             «transformDataContainerBody(type, type.allProperties, node)»
447                             return ($r) _childNodes;
448                         }
449                     '''
450                     setBodyChecked( body, sourceGenerator)
451                 ]
452                 method(Object, "serialize", Object) [
453                     val body = '''
454                         {
455                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
456                             «QName.name» _localName = QNAME;
457                             if(_input.getKey() != null) {
458                                 _localName = («QName.name») _input.getKey();
459                             }
460                             return toDomStatic(_localName,_input.getValue());
461                         }
462                     '''
463                     setBodyChecked( body, sourceGenerator)
464                 ]
465                 method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
466                     modifiers = PUBLIC + FINAL + STATIC
467                     setBodyChecked( deserializeBody(type, node, getBindingIdentifierByPath(node.path)),
468                                     sourceGenerator )
469                 ]
470                 method(Object, "deserialize", #[Object, InstanceIdentifier]) [
471                     val body = '''
472                         {
473                             //System.out.println("«type.name»#deserialize: " +$1);
474                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
475                             return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue(),$2);
476                         }
477                     '''
478                     setBodyChecked( body, sourceGenerator)
479                 ]
480             ]
481
482             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
483             sourceGenerator.outputGeneratedSource( ctCls )
484             listener?.onDataContainerCodecCreated(inputType, ret);
485             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
486             return ret;
487         } catch (Exception e) {
488             processException(inputType, e);
489             return null;
490         }
491     }
492
493     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
494         Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
495         try {
496
497             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
498
499             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
500             val ctCls = createClass(typeSpec.codecClassName) [
501  
502                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
503                 staticQNameField(node.QName, sourceGenerator);
504                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
505                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
506                 staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
507                 implementsType(BINDING_CODEC)
508
509                 method(Object, "toDomStatic", #[QName, Object]) [
510                     modifiers = PUBLIC + FINAL + STATIC
511                     setBodyChecked( serializeBodyFacade(typeSpec, node), sourceGenerator )
512                 ]
513                 method(Object, "serialize", Object) [
514                     val body = '''
515                         {
516                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
517                             «QName.name» _localName = QNAME;
518                             if(_input.getKey() != null) {
519                                 _localName = («QName.name») _input.getKey();
520                             }
521                             return toDomStatic(_localName,_input.getValue());
522                         }
523                     '''
524                     setBodyChecked( body, sourceGenerator )
525                 ]
526
527                 method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
528                     modifiers = PUBLIC + FINAL + STATIC
529                     setBodyChecked( deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path)),
530                                     sourceGenerator )
531                 ]
532
533                 method(Object, "deserialize", #[Object, InstanceIdentifier]) [
534                     val body = '''
535                         {
536                             «QName.name» _qname = QNAME;
537                             if($1 instanceof java.util.Map.Entry) {
538                                 _qname = («QName.name») ((java.util.Map.Entry) $1).getKey();
539                             }
540                             return fromDomStatic(_qname,$1,$2);
541                         }
542                     '''
543                     setBodyChecked( body, sourceGenerator )
544                 ]
545             ]
546
547             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
548
549             sourceGenerator.outputGeneratedSource( ctCls )
550
551             listener?.onDataContainerCodecCreated(inputType, ret);
552             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
553             return ret;
554         } catch (Exception e) {
555             processException(inputType, e);
556             return null;
557         }
558     }
559
560     private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
561         Class<?> inputType, GeneratedType type, AugmentationSchema node) {
562         try {
563
564             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
565
566             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
567             val properties = type.allProperties
568             val ctCls = createClass(type.codecClassName) [
569                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
570                 staticQNameField(node.augmentationQName, sourceGenerator);
571                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
572                 staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
573                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
574                 implementsType(BINDING_CODEC)
575
576                 method(Object, "toDomStatic", #[QName, Object]) [
577                     modifiers = PUBLIC + FINAL + STATIC
578                     val body = '''
579                         {
580                             ////System.out.println("Qname " + $1);
581                             ////System.out.println("Value " + $2);
582                             «QName.name» _resultName = «QName.name».create(QNAME,QNAME.getLocalName());
583                             java.util.List _childNodes = new java.util.ArrayList();
584                             «type.resolvedName» value = («type.resolvedName») $2;
585                             «FOR child : node.childNodes»
586                                 «var signature = properties.getFor(child)»
587                                 ////System.out.println("«signature.key»" + value.«signature.key»());
588                                 «serializeProperty(child, signature.value, signature.key)»
589                             «ENDFOR»
590                             return ($r) _childNodes;
591                         }
592                     '''
593                     setBodyChecked( body, sourceGenerator )
594                 ]
595                 method(Object, "serialize", Object) [
596                     val body = '''
597                         {
598                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
599                             «QName.name» _localName = QNAME;
600                             if(_input.getKey() != null) {
601                                 _localName = («QName.name») _input.getKey();
602                             }
603                             return toDomStatic(_localName,_input.getValue());
604                         }
605                     '''
606                     setBodyChecked( body, sourceGenerator )
607                 ]
608
609                 method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
610                     modifiers = PUBLIC + FINAL + STATIC
611                     val body = '''
612                         {
613                             «QName.name» _localQName = QNAME;
614
615                             if($2 == null) {
616                             return null;
617                             }
618                             java.util.Map _compositeNode = (java.util.Map) $2;
619                             //System.out.println(_localQName + " " + _compositeNode);
620                             «type.builderName» _builder = new «type.builderName»();
621                             boolean _is_empty = true;
622                             «FOR child : node.childNodes»
623                                 «val signature = properties.getFor(child)»
624                                 «deserializeProperty(child, signature.value, signature.key)»
625                                 _builder.«signature.key.toSetter»(«signature.key»);
626                             «ENDFOR»
627                             if(_is_empty) {
628                             return null;
629                             }
630                             return _builder.build();
631                         }
632                     '''
633                     setBodyChecked( body, sourceGenerator )
634                 ]
635
636                 method(Object, "deserialize", #[Object, InstanceIdentifier]) [
637                     val body = '''
638                         {
639                             return fromDomStatic(QNAME,$1,$2);
640                         }
641                     '''
642                     setBodyChecked( body, sourceGenerator )
643                 ]
644             ]
645
646             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
647             sourceGenerator.outputGeneratedSource( ctCls )
648             listener?.onDataContainerCodecCreated(inputType, ret);
649             return ret;
650         } catch (Exception e) {
651             processException(inputType, e);
652             return null;
653         }
654     }
655
656     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
657         Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
658         try {
659
660             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
661
662             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
663             val ctCls = createClass(typeSpec.codecClassName) [
664                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
665                 //staticQNameField(inputType);
666                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
667                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
668                 staticField(it, DISPATCH_CODEC, BindingCodec, sourceGenerator)
669                 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
670                 implementsType(BINDING_CODEC)
671                 method(List, "toDomStatic", #[QName, Object]) [
672                     modifiers = PUBLIC + FINAL + STATIC
673                     val body = '''
674                         {
675                             if($2 == null) {
676                                 return null;
677                             }
678                             if («DISPATCH_CODEC» == null) {
679                                 throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
680                             }
681                             java.util.Map.Entry _input = new «SimpleEntry.name»($1,$2);
682                             Object _ret =  «DISPATCH_CODEC».serialize(_input);
683                             ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
684                             return («List.name») _ret;
685                         }
686                     '''
687                     setBodyChecked( body, sourceGenerator )
688                 ]
689                 method(Object, "serialize", Object) [
690                     val body = '''
691                         {
692                             throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
693                         }
694                     '''
695                     setBodyChecked( body, sourceGenerator )
696                 ]
697                 method(Object, "fromDomStatic", #[QName, Map, InstanceIdentifier]) [
698                     modifiers = PUBLIC + FINAL + STATIC
699                     val body = '''
700                         {
701                             if («DISPATCH_CODEC» == null) {
702                                 throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
703                             }
704                             return «DISPATCH_CODEC».deserialize($2,$3);
705                         }
706                     '''
707                     setBodyChecked( body, sourceGenerator )
708                 ]
709                 method(Object, "deserialize", #[Object, InstanceIdentifier]) [
710                     val body = '''
711                         {
712                             throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
713                         }
714                     '''
715                     setBodyChecked( body, sourceGenerator )
716                 ]
717             ]
718
719             val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
720             sourceGenerator.outputGeneratedSource( ctCls )
721             val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
722             listener?.onChoiceCodecCreated(inputType, ret, node);
723             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
724             return ret;
725         } catch (Exception e) {
726             processException(inputType, e);
727             return null;
728         }
729     }
730
731     private def keyConstructorList(List<QName> qnames) {
732         val names = new TreeSet<String>()
733         for (name : qnames) {
734             val fieldName = name.getterName;
735             names.add(fieldName);
736         }
737         return Joiner.on(",").join(names);
738     }
739
740     private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
741         val ret = serializeBody(type, node);
742         return ret;
743     }
744
745     private def String deserializeBody(GeneratedType type, SchemaNode node, InstanceIdentifier<?> bindingId) {
746         val ret = deserializeBodyImpl(type, node, bindingId);
747         return ret;
748     }
749
750     private def deserializeKey(GeneratedType type, ListSchemaNode node) {
751         if (node.keyDefinition != null && !node.keyDefinition.empty) {
752             return '''
753                 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
754                 _builder.setKey(getKey);
755             ''';
756         }
757     }
758
759     private def String deserializeBodyWithAugmentations(GeneratedType type, DataNodeContainer node, InstanceIdentifier<?> bindingId) '''
760         {
761             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
762             if($2 == null) {
763                 return null;
764             }
765             java.util.Map _compositeNode = (java.util.Map) $2;
766             //System.out.println(_localQName + " " + _compositeNode);
767             «type.builderName» _builder = new «type.builderName»();
768             «deserializeDataNodeContainerBody(type, node, bindingId)»
769             «type.deserializeAugmentations»
770             return _builder.build();
771         }
772     '''
773
774     private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node, InstanceIdentifier<?> bindingId) '''
775         {
776             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
777
778             if($2 == null) {
779             return null;
780             }
781             java.util.Map _compositeNode = (java.util.Map) $2;
782             «type.builderName» _builder = new «type.builderName»();
783             return _builder.build();
784         }
785     '''
786
787     private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node, InstanceIdentifier<?> bindingId) '''
788         {
789             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
790             if($2 == null) {
791                 return null;
792             }
793             java.util.Map _compositeNode = (java.util.Map) $2;
794             //System.out.println(_localQName + " " + _compositeNode);
795             «type.builderName» _builder = new «type.builderName»();
796             «deserializeKey(type, node)»
797             «deserializeDataNodeContainerBody(type, node, bindingId)»
798             «type.deserializeAugmentations»
799             return _builder.build();
800         }
801     '''
802
803     private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node, InstanceIdentifier<?> bindingId) {
804         return deserializeBodyWithAugmentations(type, node, bindingId);
805     }
806
807     private def dispatch String deserializeBodyImpl(GeneratedType type, NotificationDefinition node, InstanceIdentifier<?> bindingId) {
808         return deserializeBodyWithAugmentations(type, node, bindingId);
809     }
810
811     private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node, InstanceIdentifier<?> bindingId) {
812         return deserializeBodyWithAugmentations(type, node, bindingId);
813     }
814
815     private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node, InstanceIdentifier<?> bindingId) {
816         deserializeNodeContainerBodyImpl(type, type.allProperties, node, bindingId);
817     }
818
819     private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
820         DataNodeContainer node, InstanceIdentifier<?> bindingId) {
821         val ret = '''
822             boolean _is_empty = true;
823             «FOR child : node.childNodes»
824                 «val signature = properties.getFor(child)»
825                 «IF signature !== null»
826                     «deserializeProperty(child, signature.value, signature.key)»
827                     _builder.«signature.key.toSetter»(«signature.key»);
828                 «ENDIF»
829             «ENDFOR»
830         '''
831         return ret;
832     }
833
834     def deserializeAugmentations(GeneratedType type) '''
835         «InstanceIdentifier.resolvedName» iid = $3.builder().child(«type.resolvedName».class).build();
836         java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode,$3);
837         if(_augmentation != null) {
838             «Iterator.name» _entries = _augmentation.entrySet().iterator();
839             while(_entries.hasNext()) {
840                 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
841                 ////System.out.println("Aug. key:" + _entry.getKey());
842                 Class _type = (Class) _entry.getKey();
843                 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
844                 if(_value != null) {
845                     _builder.addAugmentation(_type,_value);
846                 }
847             }
848         }
849     '''
850
851     private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
852         String propertyName) '''
853         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
854             localName»"));
855         ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
856         java.util.List «propertyName» = new java.util.ArrayList();
857         if(_dom_«propertyName» != null) {
858             java.util.List _serialized = new java.util.ArrayList();
859             java.util.Iterator _iterator = _dom_«propertyName».iterator();
860             boolean _hasNext = _iterator.hasNext();
861             while(_hasNext) {
862                 Object _listItem = _iterator.next();
863                 _is_empty = false;
864                 ////System.out.println("  item" + _listItem);
865                 «val param = type.actualTypeArguments.get(0)»
866                 «InstanceIdentifier.resolvedName» iid = $3.builder().child(«param.resolvedName».class).build();
867                 Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem,iid);
868                 ////System.out.println("  value" + _value);
869                 «propertyName».add(_value);
870                 _hasNext = _iterator.hasNext();
871             }
872         }
873
874         ////System.out.println(" list" + «propertyName»);
875     '''
876
877     private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
878         String propertyName) '''
879         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
880             localName»"));
881         java.util.List «propertyName» = new java.util.ArrayList();
882         if(_dom_«propertyName» != null) {
883             java.util.List _serialized = new java.util.ArrayList();
884             java.util.Iterator _iterator = _dom_«propertyName».iterator();
885             boolean _hasNext = _iterator.hasNext();
886             while(_hasNext) {
887                 _is_empty = false;
888                 Object _listItem = _iterator.next();
889                 if(_listItem instanceof java.util.Map.Entry) {
890                     Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
891                     Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue", schema.type)»;
892                     «propertyName».add(_value);
893                 }
894                 _hasNext = _iterator.hasNext();
895             }
896         }
897     '''
898
899     private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
900         java.util.List _dom_«propertyName»_list =
901             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
902         «type.resolvedName» «propertyName» = null;
903         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
904             _is_empty = false;
905             java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
906             Object _inner_value = _dom_«propertyName».getValue();
907             «propertyName» = «deserializeValue(type, "_inner_value", schema.type)»;
908         }
909     '''
910
911     private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
912         String propertyName) '''
913         java.util.List _dom_«propertyName»_list =
914             _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
915         «type.resolvedName» «propertyName» = null;
916         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
917             _is_empty = false;
918             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
919             «InstanceIdentifier.resolvedName» iid = $3.builder().child(«type.resolvedName».class).build();
920             «propertyName» =  «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»,iid);
921         }
922     '''
923
924     private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
925         «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode,$3);
926         if(«propertyName» != null) {
927             _is_empty = false;
928         }
929     '''
930
931     private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter,
932         TypeDefinition<?> typeDefinition) '''
933         («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
934     '''
935
936     private def dispatch String deserializeValue(Enumeration type, String domParameter, TypeDefinition<?> typeDefinition) '''
937         («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
938     '''
939
940     private def dispatch String deserializeValue(Type type, String domParameter, TypeDefinition<?> typeDef) {
941         if (INSTANCE_IDENTIFIER.equals(type)) {
942             return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
943         } else if (CLASS_TYPE.equals(type)) {
944             return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
945         } else if (typeDef!=null && typeDef instanceof EmptyTypeDefinition) {
946             if(domParameter == null) {
947                 return ''' Boolean.FALSE '''
948             } else {
949                 return ''' Boolean.TRUE '''
950             }
951         }
952         return '''(«type.resolvedName») «domParameter»'''
953     }
954
955     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
956         Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
957         try {
958
959             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
960
961             val returnType = typeSpec.valueReturnType;
962             if (returnType == null) {
963                 val ctCls = createDummyImplementation(inputType, typeSpec, sourceGenerator);
964                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
965                 sourceGenerator.outputGeneratedSource( ctCls )
966                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
967             }
968
969             val ctCls = createClass(typeSpec.codecClassName) [
970                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
971                 if (inputType.isYangBindingAvailable) {
972                     implementsType(BINDING_CODEC)
973                     staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
974                     staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
975                     implementsType(BindingDeserializer.asCtClass)
976                 }
977                 method(Object, "toDomValue", Object) [
978                     modifiers = PUBLIC + FINAL + STATIC
979                     val ctSpec = typeSpec.asCtClass;
980                     val body = '''
981                         {
982                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
983
984                             if($1 == null) {
985                             return null;
986                             }
987                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
988                             ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
989                             «returnType.resolvedName» _value =  _encapsulatedValue.getValue();
990                             ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
991                             Object _domValue = «serializeValue(returnType, "_value", null)»;
992                             return _domValue;
993                         }
994                     '''
995                     setBodyChecked( body, sourceGenerator )
996                 ]
997                 method(Object, "serialize", Object) [
998                     val body = '''
999                         {
1000                             return toDomValue($1);
1001                         }
1002                     '''
1003                     setBodyChecked( body, sourceGenerator )
1004                 ]
1005                 method(Object, "fromDomValue", Object) [
1006                     modifiers = PUBLIC + FINAL + STATIC
1007                     val body = '''
1008                         {
1009                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
1010
1011                             if($1 == null) {
1012                             return null;
1013                             }
1014                             «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1", null)»;
1015                             «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
1016                             return _value;
1017                         }
1018                     '''
1019                     setBodyChecked( body, sourceGenerator )
1020                 ]
1021                 method(Object, "deserialize", Object) [
1022                     val body = '''
1023                         {
1024                             return fromDomValue($1);
1025                         }
1026                     '''
1027                     setBodyChecked( body, sourceGenerator )
1028                 ]
1029             ]
1030
1031             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
1032             sourceGenerator.outputGeneratedSource( ctCls )
1033             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
1034             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
1035         } catch (Exception e) {
1036             LOG.error("Cannot compile DOM Codec for {}", inputType, e);
1037             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
1038             exception.addSuppressed(e);
1039             throw exception;
1040         }
1041     }
1042
1043     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
1044         Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
1045         try {
1046             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
1047
1048             val ctCls = createClass(typeSpec.codecClassName) [
1049                 val properties = typeSpec.allProperties;
1050                 val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type|type.QName.getterName];
1051                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
1052                 if (inputType.isYangBindingAvailable) {
1053                     implementsType(BINDING_CODEC)
1054                     staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
1055                     staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
1056                     implementsType(BindingDeserializer.asCtClass)
1057                 }
1058                 method(Object, "toDomValue", Object) [
1059                     modifiers = PUBLIC + FINAL + STATIC
1060                     val ctSpec = inputType.asCtClass;
1061                     val body = '''
1062                         {
1063                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
1064
1065                             if($1 == null) {
1066                             return null;
1067                             }
1068                             «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
1069                             «FOR property : properties.entrySet»
1070                             «IF property.key != "getValue"»
1071                                 «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.
1072                             key»();
1073                                 if(«property.key» != null) {
1074                                     return «serializeValue(property.value, property.key,
1075                             getterToTypeDefinition.get(property.key))»;
1076                                 }
1077                             «ENDIF»
1078                             «ENDFOR»
1079
1080                             return null;
1081                         }
1082                     '''
1083                     setBodyChecked( body, sourceGenerator )
1084                 ]
1085                 method(Object, "serialize", Object) [
1086                     val body = '''
1087                         {
1088                             return toDomValue($1);
1089                         }
1090                     '''
1091                     setBodyChecked( body, sourceGenerator )
1092                 ]
1093                 method(Object, "fromDomValue", Object) [
1094                     modifiers = PUBLIC + FINAL + STATIC
1095                     val body = '''
1096                         {
1097                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
1098
1099                             if($1 == null) {
1100                             return null;
1101                             }
1102                             if($1 instanceof String) {
1103                             String _simpleValue = (String) $1;
1104                             return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
1105                             }
1106                             return null;
1107                         }
1108                     '''
1109                     setBodyChecked( body, sourceGenerator )
1110                 ]
1111                 method(Object, "deserialize", Object) [
1112                     val body = '''
1113                         {
1114                             return fromDomValue($1);
1115                         }
1116                     '''
1117                     setBodyChecked( body, sourceGenerator )
1118                 ]
1119             ]
1120
1121             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
1122             sourceGenerator.outputGeneratedSource( ctCls )
1123             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
1124             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
1125         } catch (Exception e) {
1126             LOG.error("Cannot compile DOM Codec for {}", inputType, e);
1127             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
1128             exception.addSuppressed(e);
1129             throw exception;
1130         }
1131     }
1132
1133     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
1134         Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
1135         try {
1136             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
1137
1138             val ctCls = createClass(typeSpec.codecClassName) [
1139                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
1140                 if (inputType.isYangBindingAvailable) {
1141                     implementsType(BINDING_CODEC)
1142                     staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
1143                     staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
1144                     implementsType(BindingDeserializer.asCtClass)
1145                 }
1146                 method(Object, "toDomValue", Object) [
1147                     modifiers = PUBLIC + FINAL + STATIC
1148                     val ctSpec = typeSpec.asCtClass;
1149                     val body = '''
1150                         {
1151                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
1152
1153                             if($1 == null) {
1154                             return null;
1155                             }
1156                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
1157                             «HashSet.resolvedName» _value = new «HashSet.resolvedName»();
1158                             //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
1159
1160                             «FOR bit : typeDef.bits»
1161                             «val getter = bit.getterName()»
1162                             if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
1163                                 _value.add("«bit.name»");
1164                             }
1165                             «ENDFOR»
1166                             «Set.resolvedName» _domValue =  «Collections.resolvedName».unmodifiableSet(_value);
1167                             //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
1168
1169                             return _domValue;
1170                         }
1171                     '''
1172                     setBodyChecked( body, sourceGenerator )
1173                 ]
1174                 method(Object, "serialize", Object) [
1175                     val body = '''
1176                         {
1177                             return toDomValue($1);
1178                         }
1179                     '''
1180                     setBodyChecked( body, sourceGenerator )
1181                 ]
1182                 method(Object, "fromDomValue", Object) [
1183                     modifiers = PUBLIC + FINAL + STATIC
1184                     val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
1185                     val body = '''
1186                         {
1187                             //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
1188
1189                             if($1 == null) {
1190                             return null;
1191                             }
1192                             «Set.resolvedName» _domValue = («Set.resolvedName») $1;
1193                             «FOR bit : sortedBits»
1194                             Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
1195                             «ENDFOR»
1196
1197                             return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
1198                         }
1199                     '''
1200                     setBodyChecked( body, sourceGenerator )
1201                 ]
1202                 method(Object, "deserialize", Object) [
1203                     val body = '''
1204                         {
1205                             return fromDomValue($1);
1206                         }
1207                     '''
1208                     setBodyChecked( body, sourceGenerator )
1209                 ]
1210             ]
1211
1212             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
1213             sourceGenerator.outputGeneratedSource( ctCls )
1214             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
1215             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
1216         } catch (Exception e) {
1217             LOG.error("Cannot compile DOM Codec for {}", inputType, e);
1218             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
1219             exception.addSuppressed(e);
1220             throw exception;
1221         }
1222     }
1223
1224     def String getPropertyName(Bit bit) {
1225         '''_«BindingGeneratorUtil.parseToValidParamName(bit.name)»'''
1226     }
1227
1228     def String getterName(Bit bit) {
1229
1230         val paramName = BindingGeneratorUtil.parseToValidParamName(bit.name);
1231         return '''is«paramName.toFirstUpper»''';
1232     }
1233
1234     def boolean isYangBindingAvailable(Class<?> class1) {
1235         try {
1236             val bindingCodecClass = class1.classLoader.loadClass(BINDING_CODEC.name);
1237             return bindingCodecClass !== null;
1238         } catch (ClassNotFoundException e) {
1239             return false;
1240         }
1241     }
1242
1243     private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec,
1244                                           SourceCodeGenerator sourceGenerator ) {
1245         LOG.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
1246         return createClass(typeSpec.codecClassName) [
1247             if (object.isYangBindingAvailable) {
1248                 implementsType(BINDING_CODEC)
1249                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
1250                 staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
1251                 implementsType(BindingDeserializer.asCtClass)
1252             }
1253             //implementsType(BindingDeserializer.asCtClass)
1254             method(Object, "toDomValue", Object) [
1255                 modifiers = PUBLIC + FINAL + STATIC
1256                 val body = '''
1257                     {
1258                         if($1 == null) {
1259                             return null;
1260                         }
1261                         return $1.toString();
1262                     }'''
1263                 setBodyChecked( body, sourceGenerator )
1264             ]
1265             method(Object, "serialize", Object) [
1266                 val body = '''
1267                     {
1268                         return toDomValue($1);
1269                     }
1270                 '''
1271                 setBodyChecked( body, sourceGenerator )
1272             ]
1273             method(Object, "fromDomValue", Object) [
1274                 modifiers = PUBLIC + FINAL + STATIC
1275                 val body = '''return null;'''
1276                 setBodyChecked( body, sourceGenerator )
1277             ]
1278             method(Object, "deserialize", Object) [
1279                 val body = '''
1280                     {
1281                         return fromDomValue($1);
1282                     }
1283                     '''
1284                 setBodyChecked( body, sourceGenerator )
1285             ]
1286         ]
1287     }
1288
1289     private def Type getValueReturnType(GeneratedTransferObject object) {
1290         for (prop : object.properties) {
1291             if (prop.name == "value") {
1292                 return prop.returnType;
1293             }
1294         }
1295         if (object.superType != null) {
1296             return getValueReturnType(object.superType);
1297         }
1298         return null;
1299     }
1300
1301     private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec, TypeDefinition<?> type) {
1302         var EnumerationType enumSchemaType
1303         if (type instanceof EnumerationType) {
1304             enumSchemaType = type as EnumerationType
1305         } else {
1306             val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
1307             val schema = getSchemaNode(typeRef) as ExtendedType;
1308             enumSchemaType = schema.baseType as EnumerationType;
1309         }
1310         val enumSchema = enumSchemaType;
1311         try {
1312             val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
1313
1314             //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
1315             val ctCls = createClass(typeSpec.codecClassName) [
1316                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
1317                 //implementsType(BINDING_CODEC)
1318                 method(Object, "toDomValue", Object) [
1319                     modifiers = PUBLIC + FINAL + STATIC
1320                     val body = '''
1321                         {
1322                             if($1 == null) {
1323                                 return null;
1324                             }
1325                             «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
1326                             «FOR en : enumSchema.values»
1327                             if(«typeSpec.resolvedName».«BindingMapping.getClassName(en.name)».equals(_value)) {
1328                                 return "«en.name»";
1329                             }
1330                             «ENDFOR»
1331                             return null;
1332                         }
1333                     '''
1334                     setBodyChecked( body, sourceGenerator )
1335                 ]
1336                 method(Object, "serialize", Object) [
1337                     val body = '''
1338                         {
1339                             return toDomValue($1);
1340                         }
1341                     '''
1342                     setBodyChecked( body, sourceGenerator )
1343                 ]
1344                 method(Object, "fromDomValue", Object) [
1345                     modifiers = PUBLIC + FINAL + STATIC
1346                     val body = '''
1347                         {
1348                             if($1 == null) {
1349                                 return null;
1350                             }
1351                             String _value = (String) $1;
1352                             «FOR en : enumSchema.values»
1353                                 if("«en.name»".equals(_value)) {
1354                                     return «typeSpec.resolvedName».«BindingMapping.getClassName(en.name)»;
1355                                 }
1356                             «ENDFOR»
1357                             return null;
1358                         }
1359                     '''
1360                     setBodyChecked( body, sourceGenerator )
1361                 ]
1362                 method(Object, "deserialize", Object) [
1363                     val body = '''
1364                         {
1365                             return fromDomValue($1);
1366                         }
1367                     '''
1368                     setBodyChecked( body, sourceGenerator )
1369                 ]
1370             ]
1371
1372             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
1373             sourceGenerator.outputGeneratedSource( ctCls )
1374             LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
1375             return ret;
1376         } catch (CodeGenerationException e) {
1377             throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1378         } catch (Exception e) {
1379             LOG.error("Cannot compile DOM Codec for {}", inputType, e);
1380             val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
1381             exception.addSuppressed(e);
1382             throw exception;
1383         }
1384
1385     }
1386
1387     def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
1388         val cls = newClass.toClass(loader, domain);
1389         if (classFileCapturePath !== null) {
1390             newClass.writeFile(classFileCapturePath.absolutePath);
1391         }
1392         listener?.onCodecCreated(cls);
1393         return cls;
1394     }
1395
1396     def debugWriteClass(CtClass class1) {
1397         val path = class1.name.replace(".", "/") + ".class"
1398
1399         val captureFile = new File(classFileCapturePath, path);
1400         captureFile.createNewFile
1401
1402     }
1403
1404     /**
1405      * Default catch all
1406      *
1407      **/
1408     private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1409         «type.resolvedName» «propertyName» = null;
1410     '''
1411
1412     private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1413         String propertyName) {
1414         _deserializeProperty(container, type.toInstance, propertyName)
1415     }
1416
1417     static def toSetter(String it) {
1418
1419         if (startsWith("is")) {
1420             return "set" + substring(2);
1421         } else if (startsWith("get")) {
1422             return "set" + substring(3);
1423         }
1424         return "set" + it;
1425     }
1426
1427     /*
1428     private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
1429         «type.resolvedName» «propertyName» = value.«propertyName»();
1430         if(«propertyName» != null) {
1431             Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
1432             _childNodes.add(domValue);
1433         }
1434     '''
1435     */
1436     private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
1437
1438     private def staticQNameField(CtClass it, QName node, SourceCodeGenerator sourceGenerator) {
1439         val field = new CtField(ctQName, "QNAME", it);
1440         field.modifiers = PUBLIC + FINAL + STATIC;
1441         val code = '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")'''
1442         addField(field, code )
1443
1444         sourceGenerator.appendField( field, code );
1445     }
1446
1447     private def String serializeBodyImpl(GeneratedType type, DataNodeContainer nodeContainer) '''
1448         {
1449             «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1450             java.util.List _childNodes = new java.util.ArrayList();
1451             «type.resolvedName» value = («type.resolvedName») $2;
1452             «transformDataContainerBody(type, type.allProperties, nodeContainer)»
1453             «serializeAugmentations»
1454             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1455         }
1456     '''
1457
1458     private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) {
1459         return serializeBodyImpl(type, node);
1460     }
1461
1462     private def dispatch String serializeBody(GeneratedType type, NotificationDefinition node) {
1463         return serializeBodyImpl(type, node);
1464     }
1465
1466     private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) {
1467         return serializeBodyImpl(type, node);
1468     }
1469
1470     private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) {
1471         return serializeBodyImpl(type, node);
1472     }
1473
1474     private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1475         {
1476         «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1477             java.util.List _childNodes = new java.util.ArrayList();
1478             «type.resolvedName» value = («type.resolvedName») $2;
1479             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1480         }
1481     '''
1482
1483     private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
1484         val ret = '''
1485             «FOR child : node.childNodes»
1486                 «val signature = properties.getFor(child)»
1487                 «IF signature !== null»
1488                     ////System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
1489                     «serializeProperty(child, signature.value, signature.key)»
1490                 «ENDIF»
1491             «ENDFOR»
1492         '''
1493         return ret;
1494     }
1495
1496     private static def serializeAugmentations() '''
1497         java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1498         if(_augmentations != null) {
1499             _childNodes.addAll(_augmentations);
1500         }
1501     '''
1502
1503     private static def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1504         var sig = map.get(node.getterName);
1505         if (sig != null) {
1506             return new SimpleEntry(node.getterName, sig);
1507         }
1508         sig = map.get(node.booleanGetterName);
1509         if (sig != null) {
1510             return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1511         }
1512         return null;
1513     }
1514
1515     private static def String getBooleanGetterName(DataSchemaNode node) {
1516         return "is" + BindingMapping.getPropertyName(node.QName.localName).toFirstUpper;
1517     }
1518
1519     private static def String getGetterName(DataSchemaNode node) {
1520         return "get" + BindingMapping.getPropertyName(node.QName.localName).toFirstUpper;
1521     }
1522
1523     private static def String getGetterName(QName node) {
1524         return "get" + BindingMapping.getPropertyName(node.localName).toFirstUpper;
1525     }
1526
1527     private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1528         String propertyName) '''
1529         «type.resolvedName» «propertyName» = value.«propertyName»();
1530         ////System.out.println("«propertyName»:" + «propertyName»);
1531         if(«propertyName» != null) {
1532             java.util.Iterator _iterator = «propertyName».iterator();
1533             boolean _hasNext = _iterator.hasNext();
1534             while(_hasNext) {
1535                 Object _listItem = _iterator.next();
1536                 Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
1537                 _childNodes.add(_domValue);
1538                 _hasNext = _iterator.hasNext();
1539             }
1540         }
1541     '''
1542
1543     private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1544         «type.resolvedName» «propertyName» = value.«propertyName»();
1545
1546         if(«propertyName» != null) {
1547             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1548             Object _propValue = «serializeValue(type, propertyName, schema.type)»;
1549             if(_propValue != null) {
1550                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1551                 _childNodes.add(_domValue);
1552             }
1553         }
1554     '''
1555
1556     private def dispatch serializeValue(GeneratedTransferObject type, String parameter, TypeDefinition<?> typeDefinition) {
1557         '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
1558     }
1559
1560     private def dispatch serializeValue(Enumeration type, String parameter, TypeDefinition<?> typeDefinition) {
1561         '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
1562     }
1563
1564     private def dispatch serializeValue(Type type, String parameter, EmptyTypeDefinition typeDefinition) {
1565         '''(«parameter».booleanValue() ? "" : null)'''
1566     }
1567
1568     private def dispatch serializeValue(Type signature, String property, TypeDefinition<?> typeDefinition) {
1569         serializeValue(signature,property)
1570     }
1571
1572     private def dispatch serializeValue(Type signature, String property, Void typeDefinition) {
1573         serializeValue(signature,property)
1574     }
1575
1576     private def dispatch serializeValue(Type signature, String property) {
1577         if (INSTANCE_IDENTIFIER == signature) {
1578             return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1579         } else if (CLASS_TYPE.equals(signature)) {
1580             return '''(«QName.resolvedName») «IDENTITYREF_CODEC».serialize(«property»)'''
1581         }
1582         if ("char[]" == signature.name) {
1583             return '''new String(«property»)''';
1584         }
1585         return '''«property»''';
1586     }
1587
1588     private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1589         String propertyName) '''
1590         «type.resolvedName» «propertyName» = value.«propertyName»();
1591         if(«propertyName» != null) {
1592             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1593             java.util.Iterator _iterator = «propertyName».iterator();
1594             boolean _hasNext = _iterator.hasNext();
1595             while(_hasNext) {
1596                 Object _listItem = _iterator.next();
1597                 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem", schema.type)»;
1598                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1599                 _childNodes.add(_domValue);
1600                 _hasNext = _iterator.hasNext();
1601             }
1602         }
1603     '''
1604
1605     private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1606         String propertyName) '''
1607         «type.resolvedName» «propertyName» = value.«propertyName»();
1608         if(«propertyName» != null) {
1609             java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1610             _childNodes.addAll(domValue);
1611         }
1612     '''
1613
1614     /**
1615      * Default catch all
1616      *
1617      **/
1618     private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1619         «type.resolvedName» «propertyName» = value.«propertyName»();
1620         if(«propertyName» != null) {
1621             Object domValue = «propertyName»;
1622             _childNodes.add(domValue);
1623         }
1624     '''
1625
1626     private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1627         String propertyName) {
1628         serializeProperty(container, type.toInstance, propertyName)
1629     }
1630
1631     private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1632         String propertyName) '''
1633         «type.resolvedName» «propertyName» = value.«propertyName»();
1634         if(«propertyName» != null) {
1635             Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1636             _childNodes.add(domValue);
1637         }
1638     '''
1639
1640     private def codecClassName(GeneratedType typeSpec) {
1641         return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1642     }
1643
1644     private def codecClassName(Class<?> typeSpec) {
1645         return '''«typeSpec.name»$Broker$Codec$DOM'''
1646     }
1647
1648     private def HashMap<String, Type> getAllProperties(GeneratedType type) {
1649         val ret = new HashMap<String, Type>();
1650         type.collectAllProperties(ret);
1651         return ret;
1652     }
1653
1654     private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1655         for (definition : type.methodDefinitions) {
1656             set.put(definition.name, definition.returnType);
1657         }
1658         for (property : type.properties) {
1659             set.put(property.getterName, property.returnType);
1660         }
1661         for (parent : type.implements) {
1662             parent.collectAllProperties(set);
1663         }
1664     }
1665
1666     def String getGetterName(GeneratedProperty property) {
1667         return "get" + property.name.toFirstUpper
1668     }
1669
1670     private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1671         // NOOP for generic type.
1672     }
1673
1674     def String getResolvedName(Type type) {
1675         return type.asCtClass.name;
1676     }
1677
1678     def String getResolvedName(Class<?> type) {
1679         return type.asCtClass.name;
1680     }
1681
1682     def CtClass asCtClass(Type type) {
1683         val cls = loadClass(type.fullyQualifiedName)
1684         return cls.asCtClass;
1685     }
1686
1687     private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1688         LOG.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1689         throw e;
1690     }
1691
1692     private def dispatch processException(Class<?> inputType, Exception e) {
1693         LOG.error("Cannot compile DOM Codec for {}", inputType, e);
1694         val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1695         throw exception;
1696     }
1697
1698     private def setBodyChecked(CtMethod method, String body, SourceCodeGenerator sourceGenerator ) {
1699         try {
1700             method.setBody(body);
1701
1702             sourceGenerator.appendMethod( method, body );
1703         } catch (CannotCompileException e) {
1704             LOG.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
1705                 method.signature, e.message, body)
1706             throw e;
1707         }
1708     }
1709 }
1710
1711 @Data
1712 class PropertyPair {
1713
1714     String getterName;
1715
1716     Type type;
1717
1718     @Property
1719     Type returnType;
1720     @Property
1721     SchemaNode schemaNode;
1722 }