1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
3 import javassist.ClassPool
4 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
5 import org.opendaylight.yangtools.yang.model.api.SchemaNode
6 import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
7 import javassist.CtClass
9 import org.opendaylight.yangtools.yang.common.QName
10 import javassist.CtField
11 import static javassist.Modifier.*
12 import static org.opendaylight.controller.sal.binding.dom.serializer.impl.CodecMapping.*
13 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
14 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
15 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
16 import org.opendaylight.yangtools.sal.binding.model.api.Type
17 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
18 import org.opendaylight.yangtools.binding.generator.util.Types
19 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
20 import java.util.HashMap
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
22 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
24 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
26 import java.util.TreeSet
27 import com.google.common.base.Joiner
28 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
29 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
30 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
31 import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*;
32 import org.opendaylight.yangtools.yang.binding.BindingDeserializer
33 import org.opendaylight.yangtools.yang.binding.BindingCodec
34 import org.slf4j.LoggerFactory
35 import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
36 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
37 import java.security.ProtectionDomain
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
40 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
41 import java.util.Map.Entry
42 import java.util.AbstractMap.SimpleEntry
43 import org.opendaylight.yangtools.yang.binding.DataObject
44 import org.opendaylight.yangtools.yang.binding.Augmentation
45 import java.util.Iterator
46 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
47 import java.util.concurrent.ConcurrentHashMap
48 import static extension org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils.*;
50 class TransformerGenerator {
52 private static val log = LoggerFactory.getLogger(TransformerGenerator)
54 public static val STRING = Types.typeForClass(String);
55 public static val BOOLEAN = Types.typeForClass(Boolean);
56 public static val INTEGER = Types.typeForClass(Integer);
57 public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
59 //public static val DECIMAL = Types.typeForClass(Decimal);
60 public static val LONG = Types.typeForClass(Long);
62 val ClassPool classPool
63 val extension JavassistUtils utils;
70 var File classFileCapturePath;
73 var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
76 var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
79 var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
82 var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
85 var GeneratorListener listener;
87 public new(ClassPool pool) {
89 utils = new JavassistUtils(pool)
91 BINDING_CODEC = BindingCodec.asCtClass;
92 ctQName = QName.asCtClass
95 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
96 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
97 val ret = getGeneratedClass(inputType)
99 listener.onClassProcessed(inputType);
100 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
102 val ref = Types.typeForClass(inputType)
103 val node = typeToSchemaNode.get(ref)
104 val typeSpecBuilder = typeToDefinition.get(ref)
105 val typeSpec = typeSpecBuilder.toInstance();
106 val newret = generateTransformerFor(inputType, typeSpec, node);
107 listener.onClassProcessed(inputType);
108 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
112 def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
113 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
114 val ret = getGeneratedClass(inputType)
116 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
118 val ref = Types.typeForClass(inputType)
119 val node = typeToAugmentation.get(ref)
120 val typeSpecBuilder = typeToDefinition.get(ref)
121 val typeSpec = typeSpecBuilder.toInstance();
122 val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
123 listener.onClassProcessed(inputType);
124 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
128 def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
129 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
130 val ret = getGeneratedClass(inputType)
132 return ret as Class<? extends BindingCodec<Object, Object>>;
134 val ref = Types.typeForClass(inputType)
135 val typeSpecBuilder = typeToDefinition.get(ref)
136 val typeSpec = typeSpecBuilder.toInstance();
137 val newret = generateCaseCodec(inputType, typeSpec, node);
138 return newret as Class<? extends BindingCodec<Object, Object>>;
142 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
143 return withClassLoaderAndLock(parentType.classLoader, lock) [ |
144 val inputName = parentType.name + "Key";
145 val inputType = loadClassWithTCCL(inputName);
146 val ret = getGeneratedClass(inputType)
148 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
150 val ref = Types.typeForClass(parentType)
151 val node = typeToSchemaNode.get(ref) as ListSchemaNode
152 val typeSpecBuilder = typeToDefinition.get(ref)
153 val typeSpec = typeSpecBuilder.identifierDefinition;
154 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
155 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
159 def getIdentifierDefinition(GeneratedTypeBuilder builder) {
160 val inst = builder.toInstance
161 val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
162 return keyMethod.returnType as GeneratedTransferObject
165 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
166 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
167 val ret = getGeneratedClass(inputType)
169 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
171 val ref = Types.typeForClass(inputType)
172 val node = typeToSchemaNode.get(ref) as ListSchemaNode
173 val typeSpecBuilder = typeToDefinition.get(ref)
174 val typeSpec = typeSpecBuilder.toInstance();
175 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
176 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
180 private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
181 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
182 val transformer = getGeneratedClass(inputType)
183 if (transformer != null) {
186 val newret = generateKeyTransformerFor(inputType, type, schema);
187 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
191 private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
194 return loadClassWithTCCL(cls.codecClassName)
195 } catch (ClassNotFoundException e) {
200 private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
201 val cls = loadClassWithTCCL(type.resolvedName + "Key");
202 keyTransformerFor(cls, type, node);
205 private def serializer(Type type) {
206 val cls = loadClassWithTCCL(type.resolvedName);
212 private def Class<?> getValueSerializer(GeneratedTransferObject type) {
213 val cls = loadClassWithTCCL(type.resolvedName);
214 val transformer = cls.generatedClass;
215 if (transformer !== null) {
218 return withClassLoaderAndLock(cls.classLoader, lock) [ |
219 val valueTransformer = generateValueTransformer(cls, type);
220 return valueTransformer;
224 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
227 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
228 val properties = typeSpec.allProperties;
229 val ctCls = createClass(inputType.codecClassName) [
230 //staticField(Map,"AUGMENTATION_SERIALIZERS");
231 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
232 staticQNameField(node.QName);
233 implementsType(BINDING_CODEC)
234 method(Object, "toDomStatic", QName, Object) [
235 modifiers = PUBLIC + FINAL + STATIC
238 «QName.name» _resultName;
240 _resultName = «QName.name».create($1,QNAME.getLocalName());
244 java.util.List _childNodes = new java.util.ArrayList();
245 «inputType.resolvedName» value = («inputType.name») $2;
246 «FOR key : node.keyDefinition»
247 «val propertyName = key.getterName»
248 «val keyDef = node.getDataChildByName(key)»
249 «val property = properties.get(propertyName)»
250 «serializeProperty(keyDef, property, propertyName)»;
252 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
256 method(Object, "fromDomStatic", QName, Object) [
257 modifiers = PUBLIC + FINAL + STATIC
263 «QName.name» _localQName = $1;
264 java.util.Map _compositeNode = (java.util.Map) $2;
265 boolean _is_empty = true;
266 «FOR key : node.keyDefinition»
267 «val propertyName = key.getterName»
268 «val keyDef = node.getDataChildByName(key)»
269 «val property = properties.get(propertyName)»
270 «deserializeProperty(keyDef, property, propertyName)»;
272 «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
273 keyConstructorList»);
278 method(Object, "serialize", Object) [
281 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
282 «QName.name» _localQName = («QName.name») _input.getKey();
283 «inputType.name» _keyValue = («inputType.name») _input.getValue();
284 return toDomStatic(_localQName,_keyValue);
288 method(Object, "deserialize", Object) [
290 return fromDomStatic(QNAME,$1);
294 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
295 log.info("DOM Codec for {} was generated {}", inputType, ret)
296 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
297 } catch (Exception e) {
298 processException(inputType, e);
303 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
304 ChoiceCaseNode node) {
307 //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
308 val ctCls = createClass(type.codecClassName) [
309 //staticField(Map,"AUGMENTATION_SERIALIZERS");
310 implementsType(BINDING_CODEC)
311 staticQNameField(node.QName);
312 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
313 staticField(it, AUGMENTATION_CODEC, BindingCodec)
314 method(Object, "toDomStatic", QName, Object) [
315 modifiers = PUBLIC + FINAL + STATIC
318 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
319 java.util.List _childNodes = new java.util.ArrayList();
320 «type.resolvedName» value = («type.resolvedName») $2;
321 «transformDataContainerBody(type, type.allProperties, node)»
322 return ($r) _childNodes;
326 method(Object, "serialize", Object) [
329 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
330 «QName.name» _localName = QNAME;
331 if(_input.getKey() != null) {
332 _localName = («QName.name») _input.getKey();
334 return toDomStatic(_localName,_input.getValue());
338 method(Object, "fromDomStatic", QName, Object) [
339 modifiers = PUBLIC + FINAL + STATIC
340 body = deserializeBody(type, node)
342 method(Object, "deserialize", Object) [
346 return fromDomStatic(QNAME,$1);
352 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
353 log.info("DOM Codec for {} was generated {}", inputType, ret)
354 return ret as Class<? extends BindingCodec<Object, Object>>;
355 } catch (Exception e) {
356 processException(inputType, e);
361 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
362 Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
365 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
366 val ctCls = createClass(typeSpec.codecClassName) [
367 //staticField(Map,"AUGMENTATION_SERIALIZERS");
368 staticQNameField(node.QName);
369 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
370 staticField(it, AUGMENTATION_CODEC, BindingCodec)
371 implementsType(BINDING_CODEC)
372 method(Object, "toDomStatic", QName, Object) [
373 modifiers = PUBLIC + FINAL + STATIC
374 body = serializeBodyFacade(typeSpec, node)
376 method(Object, "serialize", Object) [
379 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
380 «QName.name» _localName = QNAME;
381 if(_input.getKey() != null) {
382 _localName = («QName.name») _input.getKey();
384 return toDomStatic(_localName,_input.getValue());
388 method(Object, "fromDomStatic", QName, Object) [
389 modifiers = PUBLIC + FINAL + STATIC
390 body = deserializeBody(typeSpec, node)
392 method(Object, "deserialize", Object) [
394 return fromDomStatic(QNAME,$1);
399 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
400 listener?.onDataContainerCodecCreated(inputType, ret);
401 log.info("DOM Codec for {} was generated {}", inputType, ret)
403 } catch (Exception e) {
404 processException(inputType, e);
409 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
410 Class<?> inputType, GeneratedType type, AugmentationSchema node) {
413 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
414 val properties = type.allProperties
415 val ctCls = createClass(type.codecClassName) [
416 //staticField(Map,"AUGMENTATION_SERIALIZERS");
417 staticQNameField(node.augmentationQName);
418 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
419 staticField(it, AUGMENTATION_CODEC, BindingCodec)
420 implementsType(BINDING_CODEC)
421 method(Object, "toDomStatic", QName, Object) [
422 modifiers = PUBLIC + FINAL + STATIC
425 //System.out.println("Qname " + $1);
426 //System.out.println("Value " + $2);
427 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
428 java.util.List _childNodes = new java.util.ArrayList();
429 «type.resolvedName» value = («type.resolvedName») $2;
430 «FOR child : node.childNodes»
431 «var signature = properties.getFor(child)»
432 //System.out.println("«signature.key»" + value.«signature.key»());
433 «serializeProperty(child, signature.value, signature.key)»
435 return ($r) _childNodes;
439 method(Object, "serialize", Object) [
442 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
443 «QName.name» _localName = QNAME;
444 if(_input.getKey() != null) {
445 _localName = («QName.name») _input.getKey();
447 return toDomStatic(_localName,_input.getValue());
451 method(Object, "fromDomStatic", QName, Object) [
452 modifiers = PUBLIC + FINAL + STATIC
455 «QName.name» _localQName = QNAME;
460 java.util.Map _compositeNode = (java.util.Map) $2;
461 //System.out.println(_localQName + " " + _compositeNode);
462 «type.builderName» _builder = new «type.builderName»();
463 boolean _is_empty = true;
464 «FOR child : node.childNodes»
465 «val signature = properties.getFor(child)»
466 «deserializeProperty(child, signature.value, signature.key)»
467 _builder.«signature.key.toSetter»(«signature.key»);
472 return _builder.build();
476 method(Object, "deserialize", Object) [
478 return fromDomStatic(QNAME,$1);
483 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
484 listener?.onDataContainerCodecCreated(inputType, ret);
486 } catch (Exception e) {
487 processException(inputType, e);
492 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
493 Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
496 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
497 val ctCls = createClass(typeSpec.codecClassName) [
498 //staticField(Map,"AUGMENTATION_SERIALIZERS");
499 //staticQNameField(inputType);
500 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
501 staticField(it, CLASS_TO_CASE_MAP, Map)
502 staticField(it, COMPOSITE_TO_CASE, Map)
503 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
504 implementsType(BINDING_CODEC)
505 method(List, "toDomStatic", QName, Object) [
506 modifiers = PUBLIC + FINAL + STATIC
512 «DataObject.name» _baValue = («DataObject.name») $2;
513 Class _baClass = _baValue.getImplementedInterface();
514 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
518 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
519 Object _ret = _codec.serialize(_input);
520 //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
521 return («List.name») _ret;
525 method(Object, "serialize", Object) [
527 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
530 method(Object, "fromDomStatic", QName, Map) [
531 modifiers = PUBLIC + FINAL + STATIC
534 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
536 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
542 method(Object, "deserialize", Object) [
544 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
549 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
550 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
551 listener?.onChoiceCodecCreated(inputType, ret);
552 log.info("DOM Codec for {} was generated {}", inputType, ret)
554 } catch (Exception e) {
555 processException(inputType, e);
560 private def keyConstructorList(List<QName> qnames) {
561 val names = new TreeSet<String>()
562 for (name : qnames) {
563 val fieldName = name.getterName;
564 names.add(fieldName);
566 return Joiner.on(",").join(names);
569 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
570 val ret = serializeBody(type, node);
574 private def String deserializeBody(GeneratedType type, SchemaNode node) {
575 val ret = deserializeBodyImpl(type, node);
579 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
580 if (node.keyDefinition != null && !node.keyDefinition.empty) {
582 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
583 _builder.setKey(getKey);
588 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
590 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
595 java.util.Map _compositeNode = (java.util.Map) $2;
596 «type.builderName» _builder = new «type.builderName»();
597 return _builder.build();
601 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
603 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
607 java.util.Map _compositeNode = (java.util.Map) $2;
608 «type.builderName» _builder = new «type.builderName»();
609 «deserializeKey(type, node)»
610 «deserializeDataNodeContainerBody(type, node)»
611 «deserializeAugmentations»
612 return _builder.build();
616 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
618 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
622 java.util.Map _compositeNode = (java.util.Map) $2;
623 «type.builderName» _builder = new «type.builderName»();
624 «deserializeDataNodeContainerBody(type, node)»
625 «deserializeAugmentations»
626 return _builder.build();
630 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
632 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
637 java.util.Map _compositeNode = (java.util.Map) $2;
638 //System.out.println(_localQName + " " + _compositeNode);
639 «type.builderName» _builder = new «type.builderName»();
640 «deserializeDataNodeContainerBody(type, node)»
641 «deserializeAugmentations»
642 return _builder.build();
646 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
647 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
650 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
651 DataNodeContainer node) {
653 boolean _is_empty = true;
654 «FOR child : node.childNodes»
655 «val signature = properties.getFor(child)»
656 «IF signature !== null»
657 «deserializeProperty(child, signature.value, signature.key)»
658 _builder.«signature.key.toSetter»(«signature.key»);
665 def deserializeAugmentations() '''
666 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
667 if(_augmentation != null) {
668 «Iterator.name» _entries = _augmentation.entrySet().iterator();
669 while(_entries.hasNext()) {
670 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
671 //System.out.println("Aug. key:" + _entry.getKey());
672 Class _type = (Class) _entry.getKey();
673 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
675 _builder.addAugmentation(_type,_value);
681 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
682 String propertyName) '''
683 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
685 //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
686 java.util.List «propertyName» = new java.util.ArrayList();
687 if(_dom_«propertyName» != null) {
688 java.util.List _serialized = new java.util.ArrayList();
689 java.util.Iterator _iterator = _dom_«propertyName».iterator();
690 boolean _hasNext = _iterator.hasNext();
692 Object _listItem = _iterator.next();
694 //System.out.println(" item" + _listItem);
695 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
696 //System.out.println(" value" + _value);
697 «propertyName».add(_value);
698 _hasNext = _iterator.hasNext();
702 //System.out.println(" list" + «propertyName»);
705 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
706 String propertyName) '''
707 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
709 java.util.List «propertyName» = new java.util.ArrayList();
710 if(_dom_«propertyName» != null) {
711 java.util.List _serialized = new java.util.ArrayList();
712 java.util.Iterator _iterator = _dom_«propertyName».iterator();
713 boolean _hasNext = _iterator.hasNext();
716 Object _listItem = _iterator.next();
717 if(_listItem instanceof java.util.Map.Entry) {
718 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
719 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
720 «propertyName».add(_value);
722 _hasNext = _iterator.hasNext();
727 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
728 java.util.List _dom_«propertyName»_list =
729 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
730 «type.resolvedName» «propertyName» = null;
731 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
733 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
734 Object _inner_value = _dom_«propertyName».getValue();
735 «propertyName» = «deserializeValue(type, "_inner_value")»;
739 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
740 String propertyName) '''
741 java.util.List _dom_«propertyName»_list =
742 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
743 «type.resolvedName» «propertyName» = null;
744 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
746 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
747 «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
751 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
752 «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
753 if(«propertyName» != null) {
758 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
759 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
762 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
763 Class<?> inputType, GeneratedTransferObject typeSpec) {
766 val returnType = typeSpec.valueReturnType;
767 if (returnType == null) {
768 val ctCls = createDummyImplementation(inputType, typeSpec);
769 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
770 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
772 var hasBinding = false;
774 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
775 hasBinding = bindingCodecClass !== null;
776 } catch (ClassNotFoundException e) {
779 val hasYangBinding = hasBinding
780 val ctCls = createClass(typeSpec.codecClassName) [
781 //staticField(Map,"AUGMENTATION_SERIALIZERS");
782 if (hasYangBinding) {
783 implementsType(BINDING_CODEC)
784 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
785 implementsType(BindingDeserializer.asCtClass)
787 method(Object, "toDomValue", Object) [
788 modifiers = PUBLIC + FINAL + STATIC
791 //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
796 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
797 //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
798 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
799 //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
800 Object _domValue = «serializeValue(returnType, "_value")»;
805 method(Object, "serialize", Object) [
808 return toDomValue($1);
812 method(Object, "fromDomValue", Object) [
813 modifiers = PUBLIC + FINAL + STATIC
816 //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
821 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
822 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
827 method(Object, "deserialize", Object) [
829 return fromDomValue($1);
835 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
836 log.info("DOM Codec for {} was generated {}", inputType, ret)
837 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
838 } catch (Exception e) {
839 log.error("Cannot compile DOM Codec for {}", inputType, e);
840 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
841 exception.addSuppressed(e);
847 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
848 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
849 return createClass(typeSpec.codecClassName) [
850 //staticField(Map,"AUGMENTATION_SERIALIZERS");
851 implementsType(BINDING_CODEC)
852 implementsType(BindingDeserializer.asCtClass)
853 method(Object, "toDomValue", Object) [
854 modifiers = PUBLIC + FINAL + STATIC
855 body = '''return null;'''
857 method(Object, "serialize", Object) [
860 return toDomValue($1);
864 method(Object, "fromDomValue", Object) [
865 modifiers = PUBLIC + FINAL + STATIC
866 body = '''return null;'''
868 method(Object, "deserialize", Object) [
870 return fromDomValue($1);
877 private def Type getValueReturnType(GeneratedTransferObject object) {
878 for (prop : object.properties) {
879 if (prop.name == "value") {
880 return prop.returnType;
883 if (object.superType != null) {
884 return getValueReturnType(object.superType);
889 private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
892 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
893 val ctCls = createClass(typeSpec.codecClassName) [
894 //staticField(Map,"AUGMENTATION_SERIALIZERS");
895 //implementsType(BINDING_CODEC)
896 method(Object, "toDomValue", Object) [
897 modifiers = PUBLIC + FINAL + STATIC
902 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
903 return _value.getValue();
906 method(Object, "serialize", Object) [
908 return toDomValue($1);
911 method(Object, "fromDomValue", Object) [
912 modifiers = PUBLIC + FINAL + STATIC
918 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
922 method(Object, "deserialize", Object) [
924 return fromDomValue($1);
929 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
930 log.info("DOM Codec for {} was generated {}", inputType, ret)
932 } catch (CodeGenerationException e) {
933 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
934 } catch (Exception e) {
935 log.error("Cannot compile DOM Codec for {}", inputType, e);
936 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
937 exception.addSuppressed(e);
943 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
944 val cls = newClass.toClass(loader, domain);
945 if (classFileCapturePath !== null) {
946 newClass.writeFile(classFileCapturePath.absolutePath);
948 listener?.onCodecCreated(cls);
952 def debugWriteClass(CtClass class1) {
953 val path = class1.name.replace(".", "/") + ".class"
955 val captureFile = new File(classFileCapturePath, path);
956 captureFile.createNewFile
960 private def dispatch String deserializeValue(Type type, String domParameter) {
961 if (INSTANCE_IDENTIFIER.equals(type)) {
963 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
966 return '''(«type.resolvedName») «domParameter»'''
974 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
975 «type.resolvedName» «propertyName» = null;
978 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
979 String propertyName) {
980 _deserializeProperty(container, type.toInstance, propertyName)
983 public static def toSetter(String it) {
985 if (startsWith("is")) {
986 return "set" + substring(2);
987 } else if (startsWith("get")) {
988 return "set" + substring(3);
994 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
995 «type.resolvedName» «propertyName» = value.«propertyName»();
996 if(«propertyName» != null) {
997 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
998 _childNodes.add(domValue);
1002 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
1004 private def staticQNameField(CtClass it, QName node) {
1005 val field = new CtField(ctQName, "QNAME", it);
1006 field.modifiers = PUBLIC + FINAL + STATIC;
1008 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
1011 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
1013 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1014 java.util.List _childNodes = new java.util.ArrayList();
1015 «type.resolvedName» value = («type.resolvedName») $2;
1016 «transformDataContainerBody(type, type.allProperties, node)»
1017 «serializeAugmentations»
1018 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1022 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
1024 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1025 java.util.List _childNodes = new java.util.ArrayList();
1026 «type.resolvedName» value = («type.resolvedName») $2;
1027 «transformDataContainerBody(type, type.allProperties, node)»
1028 «serializeAugmentations»
1029 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1033 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1035 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1036 java.util.List _childNodes = new java.util.ArrayList();
1037 «type.resolvedName» value = («type.resolvedName») $2;
1038 «transformDataContainerBody(type, type.allProperties, node)»
1039 «serializeAugmentations»
1040 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1044 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1046 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1047 java.util.List _childNodes = new java.util.ArrayList();
1048 «type.resolvedName» value = («type.resolvedName») $2;
1049 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1053 private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
1055 «FOR child : node.childNodes»
1056 «val signature = properties.getFor(child)»
1057 «IF signature !== null»
1058 //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
1059 «serializeProperty(child, signature.value, signature.key)»
1066 private def serializeAugmentations() '''
1067 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1068 if(_augmentations != null) {
1069 _childNodes.addAll(_augmentations);
1073 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1074 var sig = map.get(node.getterName);
1076 return new SimpleEntry(node.getterName, sig);
1078 sig = map.get(node.booleanGetterName);
1080 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1085 private static def String getBooleanGetterName(DataSchemaNode node) {
1086 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1089 private static def String getGetterName(DataSchemaNode node) {
1090 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1093 private static def String getGetterName(QName node) {
1094 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1097 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1098 String propertyName) '''
1099 «type.resolvedName» «propertyName» = value.«propertyName»();
1100 //System.out.println("«propertyName»:" + «propertyName»);
1101 if(«propertyName» != null) {
1102 java.util.Iterator _iterator = «propertyName».iterator();
1103 boolean _hasNext = _iterator.hasNext();
1105 Object _listItem = _iterator.next();
1106 Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
1107 _childNodes.add(_domValue);
1108 _hasNext = _iterator.hasNext();
1113 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1114 «type.resolvedName» «propertyName» = value.«propertyName»();
1116 if(«propertyName» != null) {
1117 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1118 Object _propValue = «serializeValue(type, propertyName)»;
1119 if(_propValue != null) {
1120 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1121 _childNodes.add(_domValue);
1126 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1127 resolvedName».toDomValue(«parameter»)'''
1129 private def dispatch serializeValue(Type signature, String property) {
1130 if (INSTANCE_IDENTIFIER == signature) {
1131 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1133 return '''«property»''';
1136 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1137 String propertyName) '''
1138 «type.resolvedName» «propertyName» = value.«propertyName»();
1139 if(«propertyName» != null) {
1140 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1141 java.util.Iterator _iterator = «propertyName».iterator();
1142 boolean _hasNext = _iterator.hasNext();
1144 Object _listItem = _iterator.next();
1145 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1146 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1147 _childNodes.add(_domValue);
1148 _hasNext = _iterator.hasNext();
1153 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1154 String propertyName) '''
1155 «type.resolvedName» «propertyName» = value.«propertyName»();
1156 if(«propertyName» != null) {
1157 java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1158 _childNodes.addAll(domValue);
1166 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1167 «type.resolvedName» «propertyName» = value.«propertyName»();
1168 if(«propertyName» != null) {
1169 Object domValue = «propertyName»;
1170 _childNodes.add(domValue);
1174 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1175 String propertyName) {
1176 serializeProperty(container, type.toInstance, propertyName)
1179 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1180 String propertyName) '''
1181 «type.resolvedName» «propertyName» = value.«propertyName»();
1182 if(«propertyName» != null) {
1183 Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1184 _childNodes.add(domValue);
1188 private def codecClassName(GeneratedType typeSpec) {
1189 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1192 private def codecClassName(Class<?> typeSpec) {
1193 return '''«typeSpec.name»$Broker$Codec$DOM'''
1196 private def HashMap<String, Type> getAllProperties(GeneratedType type) {
1197 val ret = new HashMap<String, Type>();
1198 type.collectAllProperties(ret);
1202 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1203 for (definition : type.methodDefinitions) {
1204 set.put(definition.name, definition.returnType);
1206 for (property : type.properties) {
1207 set.put(property.getterName, property.returnType);
1209 for (parent : type.implements) {
1210 parent.collectAllProperties(set);
1214 def String getGetterName(GeneratedProperty property) {
1215 return "get" + property.name.toFirstUpper
1218 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1219 // NOOP for generic type.
1222 def String getResolvedName(Type type) {
1223 return type.asCtClass.name;
1226 def String getResolvedName(Class<?> type) {
1227 return type.asCtClass.name;
1230 def CtClass asCtClass(Type type) {
1231 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1232 return cls.asCtClass;
1235 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1236 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1240 private def dispatch processException(Class<?> inputType, Exception e) {
1241 log.error("Cannot compile DOM Codec for {}", inputType, e);
1242 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1249 class PropertyPair {
1258 SchemaNode schemaNode;