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