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
49 class TransformerGenerator {
51 private static val log = LoggerFactory.getLogger(TransformerGenerator)
53 public static val STRING = Types.typeForClass(String);
54 public static val BOOLEAN = Types.typeForClass(Boolean);
55 public static val INTEGER = Types.typeForClass(Integer);
56 public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
58 //public static val DECIMAL = Types.typeForClass(Decimal);
59 public static val LONG = Types.typeForClass(Long);
61 val ClassPool classPool
62 val extension JavassistUtils utils;
69 var File classFileCapturePath;
72 var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
75 var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
78 var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
81 var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
84 var GeneratorListener listener;
86 public new(ClassPool pool) {
88 utils = new JavassistUtils(pool)
90 BINDING_CODEC = BindingCodec.asCtClass;
91 ctQName = QName.asCtClass
94 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
95 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
96 val ret = getGeneratedClass(inputType)
98 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
100 val ref = Types.typeForClass(inputType)
101 val node = typeToSchemaNode.get(ref)
102 val typeSpecBuilder = typeToDefinition.get(ref)
103 val typeSpec = typeSpecBuilder.toInstance();
104 val newret = generateTransformerFor(inputType, typeSpec, node);
105 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
109 def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
110 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
111 val ret = getGeneratedClass(inputType)
113 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
115 val ref = Types.typeForClass(inputType)
116 val node = typeToAugmentation.get(ref)
117 val typeSpecBuilder = typeToDefinition.get(ref)
118 val typeSpec = typeSpecBuilder.toInstance();
119 val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
120 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
124 def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
125 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
126 val ret = getGeneratedClass(inputType)
128 return ret as Class<? extends BindingCodec<Object, Object>>;
130 val ref = Types.typeForClass(inputType)
131 val typeSpecBuilder = typeToDefinition.get(ref)
132 val typeSpec = typeSpecBuilder.toInstance();
133 val newret = generateCaseCodec(inputType, typeSpec, node);
134 return newret as Class<? extends BindingCodec<Object, Object>>;
138 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
139 return withClassLoaderAndLock(parentType.classLoader, lock) [ |
140 val inputName = parentType.name + "Key";
141 val inputType = loadClassWithTCCL(inputName);
142 val ret = getGeneratedClass(inputType)
144 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
146 val ref = Types.typeForClass(parentType)
147 val node = typeToSchemaNode.get(ref) as ListSchemaNode
148 val typeSpecBuilder = typeToDefinition.get(ref)
149 val typeSpec = typeSpecBuilder.identifierDefinition;
150 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
151 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
155 def getIdentifierDefinition(GeneratedTypeBuilder builder) {
156 val inst = builder.toInstance
157 val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
158 return keyMethod.returnType as GeneratedTransferObject
161 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
162 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
163 val ret = getGeneratedClass(inputType)
165 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
167 val ref = Types.typeForClass(inputType)
168 val node = typeToSchemaNode.get(ref) as ListSchemaNode
169 val typeSpecBuilder = typeToDefinition.get(ref)
170 val typeSpec = typeSpecBuilder.toInstance();
171 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
172 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
176 private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
177 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
178 val transformer = getGeneratedClass(inputType)
179 if (transformer != null) {
182 val newret = generateKeyTransformerFor(inputType, type, schema);
183 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
187 private def Class getGeneratedClass(Class<? extends Object> cls) {
190 return loadClassWithTCCL(cls.codecClassName)
191 } catch (ClassNotFoundException e) {
196 private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
197 val cls = loadClassWithTCCL(type.resolvedName + "Key");
198 keyTransformerFor(cls, type, node);
201 private def serializer(Type type) {
202 val cls = loadClassWithTCCL(type.resolvedName);
208 private def Class<?> getValueSerializer(GeneratedTransferObject type) {
209 val cls = loadClassWithTCCL(type.resolvedName);
210 val transformer = cls.generatedClass;
211 if (transformer !== null) {
214 val valueTransformer = generateValueTransformer(cls, type);
215 return valueTransformer;
218 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
220 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
221 val properties = typeSpec.allProperties;
222 val ctCls = createClass(inputType.codecClassName) [
223 //staticField(Map,"AUGMENTATION_SERIALIZERS");
224 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
225 staticQNameField(node.QName);
226 implementsType(BINDING_CODEC)
227 method(Object, "toDomStatic", QName, Object) [
228 modifiers = PUBLIC + FINAL + STATIC
231 «QName.name» _resultName;
233 _resultName = «QName.name».create($1,QNAME.getLocalName());
237 java.util.List _childNodes = new java.util.ArrayList();
238 «inputType.name» value = («inputType.name») $2;
239 «FOR key : node.keyDefinition»
240 «val propertyName = key.getterName»
241 «val keyDef = node.getDataChildByName(key)»
242 «val property = properties.get(propertyName)»
243 «serializeProperty(keyDef, property, propertyName)»;
245 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
249 method(Object, "fromDomStatic", QName, Object) [
250 modifiers = PUBLIC + FINAL + STATIC
256 «QName.name» _localQName = $1;
257 java.util.Map _compositeNode = (java.util.Map) $2;
258 «FOR key : node.keyDefinition»
259 «val propertyName = key.getterName»
260 «val keyDef = node.getDataChildByName(key)»
261 «val property = properties.get(propertyName)»
262 «deserializeProperty(keyDef, property, propertyName)»;
264 «inputType.name» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
269 method(Object, "serialize", Object) [
272 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
273 «QName.name» _localQName = («QName.name») _input.getKey();
274 «inputType.name» _keyValue = («inputType.name») _input.getValue();
275 return toDomStatic(_localQName,_keyValue);
279 method(Object, "deserialize", Object) [
281 return fromDomStatic(QNAME,$1);
285 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
286 log.info("DOM Codec for {} was generated {}", inputType, ret)
287 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
288 } catch (Exception e) {
289 processException(inputType, e);
294 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
295 ChoiceCaseNode node) {
297 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
298 val ctCls = createClass(type.codecClassName) [
299 //staticField(Map,"AUGMENTATION_SERIALIZERS");
300 implementsType(BINDING_CODEC)
301 staticQNameField(inputType);
302 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
303 staticField(it, AUGMENTATION_CODEC, BindingCodec)
304 method(Object, "toDomStatic", QName, Object) [
305 modifiers = PUBLIC + FINAL + STATIC
308 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
309 java.util.List _childNodes = new java.util.ArrayList();
310 «type.resolvedName» value = («type.resolvedName») $2;
311 «transformDataContainerBody(type.allProperties, node)»
312 return ($r) _childNodes;
316 method(Object, "serialize", Object) [
319 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
320 «QName.name» _localName = QNAME;
321 if(_input.getKey() != null) {
322 _localName = («QName.name») _input.getKey();
324 return toDomStatic(_localName,_input.getValue());
328 method(Object, "fromDomStatic", QName, Object) [
329 modifiers = PUBLIC + FINAL + STATIC
330 body = deserializeBody(type, node)
332 method(Object, "deserialize", Object) [
336 return fromDomStatic(QNAME,$1);
342 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
343 log.info("DOM Codec for {} was generated {}", inputType, ret)
344 return ret as Class<? extends BindingCodec<Object, Object>>;
345 } catch (Exception e) {
346 processException(inputType, e);
351 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
352 Class inputType, GeneratedType typeSpec, SchemaNode node) {
354 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
355 val ctCls = createClass(typeSpec.codecClassName) [
356 //staticField(Map,"AUGMENTATION_SERIALIZERS");
357 staticQNameField(inputType);
358 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
359 staticField(it, AUGMENTATION_CODEC, BindingCodec)
360 implementsType(BINDING_CODEC)
361 method(Object, "toDomStatic", QName, Object) [
362 modifiers = PUBLIC + FINAL + STATIC
363 body = serializeBodyFacade(typeSpec, node)
365 method(Object, "serialize", Object) [
368 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
369 «QName.name» _localName = QNAME;
370 if(_input.getKey() != null) {
371 _localName = («QName.name») _input.getKey();
373 return toDomStatic(_localName,_input.getValue());
377 method(Object, "fromDomStatic", QName, Object) [
378 modifiers = PUBLIC + FINAL + STATIC
379 body = deserializeBody(typeSpec, node)
381 method(Object, "deserialize", Object) [
383 return fromDomStatic(QNAME,$1);
388 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
389 listener?.onDataContainerCodecCreated(inputType, ret);
390 log.info("DOM Codec for {} was generated {}", inputType, ret)
392 } catch (Exception e) {
393 processException(inputType, e);
398 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
399 Class inputType, GeneratedType type, AugmentationSchema node) {
401 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
402 val properties = type.allProperties
403 val ctCls = createClass(type.codecClassName) [
404 //staticField(Map,"AUGMENTATION_SERIALIZERS");
405 staticQNameField(inputType);
406 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
407 staticField(it, AUGMENTATION_CODEC, BindingCodec)
408 implementsType(BINDING_CODEC)
409 method(Object, "toDomStatic", QName, Object) [
410 modifiers = PUBLIC + FINAL + STATIC
413 //System.out.println("Qname " + $1);
414 //System.out.println("Value " + $2);
415 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
416 java.util.List _childNodes = new java.util.ArrayList();
417 «type.resolvedName» value = («type.resolvedName») $2;
418 «FOR child : node.childNodes»
419 «var signature = properties.getFor(child)»
420 //System.out.println("«signature.key»" + value.«signature.key»());
421 «serializeProperty(child, signature.value, signature.key)»
423 return ($r) _childNodes;
427 method(Object, "serialize", Object) [
430 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
431 «QName.name» _localName = QNAME;
432 if(_input.getKey() != null) {
433 _localName = («QName.name») _input.getKey();
435 return toDomStatic(_localName,_input.getValue());
439 method(Object, "fromDomStatic", QName, Object) [
440 modifiers = PUBLIC + FINAL + STATIC
443 «QName.name» _localQName = QNAME;
448 java.util.Map _compositeNode = (java.util.Map) $2;
449 ////System.out.println(_localQName + " " + _compositeNode);
450 «type.builderName» _builder = new «type.builderName»();
451 «FOR child : node.childNodes»
452 «val signature = properties.getFor(child)»
453 «deserializeProperty(child, signature.value, signature.key)»
455 _builder.«signature.key.toSetter»(«signature.key»);
457 return _builder.build();
461 method(Object, "deserialize", Object) [
463 return fromDomStatic(QNAME,$1);
468 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
469 listener?.onDataContainerCodecCreated(inputType, ret);
471 } catch (Exception e) {
472 processException(inputType, e);
477 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
478 Class inputType, GeneratedType typeSpec, ChoiceNode node) {
480 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
481 val ctCls = createClass(typeSpec.codecClassName) [
482 //staticField(Map,"AUGMENTATION_SERIALIZERS");
483 //staticQNameField(inputType);
484 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
485 staticField(it, CLASS_TO_CASE_MAP, Map)
486 staticField(it, COMPOSITE_TO_CASE, Map)
487 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
488 implementsType(BINDING_CODEC)
489 method(List, "toDomStatic", QName, Object) [
490 modifiers = PUBLIC + FINAL + STATIC
496 «DataObject.name» _baValue = («DataObject.name») $2;
497 Class _baClass = _baValue.getImplementedInterface();
498 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
502 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
503 return (java.util.List) _codec.serialize(_input);
507 method(Object, "serialize", Object) [
509 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
512 method(Object, "fromDomStatic", QName, Map) [
513 modifiers = PUBLIC + FINAL + STATIC
516 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
518 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
524 method(Object, "deserialize", Object) [
526 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
531 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
532 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
533 listener?.onChoiceCodecCreated(inputType, ret);
534 log.info("DOM Codec for {} was generated {}", inputType, ret)
536 } catch (Exception e) {
537 processException(inputType, e);
542 private def keyConstructorList(List<QName> qnames) {
543 val names = new TreeSet<String>()
544 for (name : qnames) {
545 val fieldName = name.getterName;
546 names.add(fieldName);
548 return Joiner.on(",").join(names);
551 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
552 val ret = serializeBody(type, node);
556 private def String deserializeBody(GeneratedType type, SchemaNode node) {
557 val ret = deserializeBodyImpl(type, node);
561 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
562 if (node.keyDefinition != null && !node.keyDefinition.empty) {
564 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
565 _builder.setKey(getKey);
570 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
572 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
577 java.util.Map _compositeNode = (java.util.Map) $2;
578 «type.builderName» _builder = new «type.builderName»();
579 return _builder.build();
583 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
585 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
589 java.util.Map _compositeNode = (java.util.Map) $2;
590 «type.builderName» _builder = new «type.builderName»();
591 «deserializeKey(type, node)»
592 «deserializeDataNodeContainerBody(type, node)»
593 «deserializeAugmentations»
594 return _builder.build();
598 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
600 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
604 java.util.Map _compositeNode = (java.util.Map) $2;
605 «type.builderName» _builder = new «type.builderName»();
606 «deserializeDataNodeContainerBody(type, node)»
607 «deserializeAugmentations»
608 return _builder.build();
612 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
614 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
619 java.util.Map _compositeNode = (java.util.Map) $2;
620 ////System.out.println(_localQName + " " + _compositeNode);
621 «type.builderName» _builder = new «type.builderName»();
622 «deserializeDataNodeContainerBody(type, node)»
623 «deserializeAugmentations»
624 return _builder.build();
628 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
629 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
632 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
633 DataNodeContainer node) {
635 «FOR child : node.childNodes.filter[!augmenting]»
636 «val signature = properties.getFor(child)»
637 «deserializeProperty(child, signature.value, signature.key)»
639 _builder.«signature.key.toSetter»(«signature.key»);
645 def deserializeAugmentations() '''
646 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
647 if(_augmentation != null) {
648 «Iterator.name» _entries = _augmentation.entrySet().iterator();
649 while(_entries.hasNext()) {
650 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
651 //System.out.println("Aug. key:" + _entry.getKey());
652 Class _type = (Class) _entry.getKey();
653 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
654 _builder.addAugmentation(_type,_value);
659 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
660 String propertyName) '''
661 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
663 ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
664 java.util.List «propertyName» = new java.util.ArrayList();
665 if(_dom_«propertyName» != null) {
666 java.util.List _serialized = new java.util.ArrayList();
667 java.util.Iterator _iterator = _dom_«propertyName».iterator();
668 boolean _hasNext = _iterator.hasNext();
670 Object _listItem = _iterator.next();
671 ////System.out.println(" item" + _listItem);
672 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
673 ////System.out.println(" value" + _value);
674 «propertyName».add(_value);
675 _hasNext = _iterator.hasNext();
679 ////System.out.println(" list" + «propertyName»);
682 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
683 String propertyName) '''
684 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
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();
693 if(_listItem instanceof java.util.Map.Entry) {
694 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
695 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
696 «propertyName».add(_value);
698 _hasNext = _iterator.hasNext();
703 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
704 java.util.List _dom_«propertyName»_list =
705 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
706 «type.resolvedName» «propertyName» = null;
707 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
708 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
709 Object _inner_value = _dom_«propertyName».getValue();
710 «propertyName» = «deserializeValue(type, "_inner_value")»;
714 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
715 String propertyName) '''
716 java.util.List _dom_«propertyName»_list =
717 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
718 «type.resolvedName» «propertyName» = null;
719 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
721 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
722 «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
726 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
727 «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
730 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
731 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
734 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
735 Class<?> inputType, GeneratedTransferObject typeSpec) {
738 val returnType = typeSpec.valueReturnType;
739 if (returnType == null) {
741 val ctCls = createDummyImplementation(inputType, typeSpec);
742 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
743 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
745 val ctCls = createClass(typeSpec.codecClassName) [
746 //staticField(Map,"AUGMENTATION_SERIALIZERS");
747 implementsType(BINDING_CODEC)
748 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
749 implementsType(BindingDeserializer.asCtClass)
750 method(Object, "toDomValue", Object) [
751 modifiers = PUBLIC + FINAL + STATIC
754 ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
759 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
760 ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
761 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
762 ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
763 Object _domValue = «serializeValue(returnType, "_value")»;
768 method(Object, "serialize", Object) [
771 return toDomValue($1);
775 method(Object, "fromDomValue", Object) [
776 modifiers = PUBLIC + FINAL + STATIC
779 ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
784 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
785 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
790 method(Object, "deserialize", Object) [
792 return fromDomValue($1);
798 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
799 log.info("DOM Codec for {} was generated {}", inputType, ret)
800 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
801 } catch (Exception e) {
802 log.error("Cannot compile DOM Codec for {}", inputType, e);
803 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
804 exception.addSuppressed(e);
810 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
811 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
812 return createClass(typeSpec.codecClassName) [
813 //staticField(Map,"AUGMENTATION_SERIALIZERS");
814 implementsType(BINDING_CODEC)
815 implementsType(BindingDeserializer.asCtClass)
816 method(Object, "toDomValue", Object) [
817 modifiers = PUBLIC + FINAL + STATIC
818 body = '''return null;'''
820 method(Object, "serialize", Object) [
823 return toDomValue($1);
827 method(Object, "fromDomValue", Object) [
828 modifiers = PUBLIC + FINAL + STATIC
829 body = '''return null;'''
831 method(Object, "deserialize", Object) [
833 return fromDomValue($1);
840 private def Type getValueReturnType(GeneratedTransferObject object) {
841 for (prop : object.properties) {
842 if (prop.name == "value") {
843 return prop.returnType;
846 if (object.superType != null) {
847 return getValueReturnType(object.superType);
852 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
853 Class<?> inputType, Enumeration typeSpec) {
855 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
856 val ctCls = createClass(typeSpec.codecClassName) [
857 //staticField(Map,"AUGMENTATION_SERIALIZERS");
858 implementsType(BINDING_CODEC)
859 method(Object, "toDomValue", Object) [
860 modifiers = PUBLIC + FINAL + STATIC
865 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
866 return _value.getValue();
869 method(Object, "serialize", Object) [
871 return toDomValue($1);
874 method(Object, "fromDomValue", Object) [
875 modifiers = PUBLIC + FINAL + STATIC
881 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
885 method(Object, "deserialize", Object) [
887 return fromDomValue($1);
892 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
893 log.info("DOM Codec for {} was generated {}", inputType, ret)
894 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
895 } catch (CodeGenerationException e) {
896 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
897 } catch (Exception e) {
898 log.error("Cannot compile DOM Codec for {}", inputType, e);
899 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
900 exception.addSuppressed(e);
906 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
907 val cls = newClass.toClass(loader, domain);
908 if (classFileCapturePath !== null) {
909 newClass.writeFile(classFileCapturePath.absolutePath);
911 listener?.onCodecCreated(cls);
915 def debugWriteClass(CtClass class1) {
916 val path = class1.name.replace(".", "/") + ".class"
918 val captureFile = new File(classFileCapturePath, path);
919 captureFile.createNewFile
923 private def dispatch String deserializeValue(Type type, String domParameter) {
924 if (INSTANCE_IDENTIFIER.equals(type)) {
926 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
929 return '''(«type.resolvedName») «domParameter»'''
937 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
938 «type.resolvedName» «propertyName» = null;
941 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
942 String propertyName) {
943 _deserializeProperty(container, type.toInstance, propertyName)
946 public static def toSetter(String it) {
948 if (startsWith("is")) {
949 return "set" + substring(2);
950 } else if (startsWith("get")) {
951 return "set" + substring(3);
957 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
958 «type.resolvedName» «propertyName» = value.«propertyName»();
959 if(«propertyName» != null) {
960 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
961 _childNodes.add(domValue);
965 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
967 private def staticQNameField(CtClass it, Class<?> node) {
968 val field = new CtField(ctQName, "QNAME", it);
969 field.modifiers = PUBLIC + FINAL + STATIC;
970 addField(field, '''«node.name».QNAME''')
973 private def staticQNameField(CtClass it, QName node) {
974 val field = new CtField(ctQName, "QNAME", it);
975 field.modifiers = PUBLIC + FINAL + STATIC;
977 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
980 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
982 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
983 java.util.List _childNodes = new java.util.ArrayList();
984 «type.resolvedName» value = («type.resolvedName») $2;
985 «transformDataContainerBody(type.allProperties, node)»
986 «serializeAugmentations»
987 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
991 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
993 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
994 java.util.List _childNodes = new java.util.ArrayList();
995 «type.resolvedName» value = («type.resolvedName») $2;
996 «transformDataContainerBody(type.allProperties, node)»
997 «serializeAugmentations»
998 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1002 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1004 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1005 java.util.List _childNodes = new java.util.ArrayList();
1006 «type.resolvedName» value = («type.resolvedName») $2;
1007 «transformDataContainerBody(type.allProperties, node)»
1008 «serializeAugmentations»
1009 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1013 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1015 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1016 java.util.List _childNodes = new java.util.ArrayList();
1017 «type.resolvedName» value = («type.resolvedName») $2;
1018 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1022 private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
1024 «FOR child : node.childNodes.filter[!augmenting]»
1025 «var signature = properties.getFor(child)»
1026 //System.out.println("«signature.key»" + value.«signature.key»());
1027 «serializeProperty(child, signature.value, signature.key)»
1033 def serializeAugmentations() '''
1034 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1035 if(_augmentations != null) {
1036 _childNodes.addAll(_augmentations);
1040 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1041 val sig = map.get(node.getterName);
1044 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1046 return new SimpleEntry(node.getterName, sig);
1049 private static def String getBooleanGetterName(DataSchemaNode node) {
1050 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1053 private static def String getGetterName(DataSchemaNode node) {
1054 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1057 private static def String getGetterName(QName node) {
1058 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1061 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1062 String propertyName) '''
1063 «type.resolvedName» «propertyName» = value.«propertyName»();
1064 if(«propertyName» != null) {
1065 java.util.Iterator _iterator = «propertyName».iterator();
1066 boolean _hasNext = _iterator.hasNext();
1068 Object _listItem = _iterator.next();
1069 Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
1070 _childNodes.add(_domValue);
1071 _hasNext = _iterator.hasNext();
1076 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1077 «type.resolvedName» «propertyName» = value.«propertyName»();
1079 if(«propertyName» != null) {
1080 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1081 Object _propValue = «serializeValue(type, propertyName)»;
1082 if(_propValue != null) {
1083 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1084 _childNodes.add(_domValue);
1089 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1090 resolvedName».toDomValue(«parameter»)'''
1092 private def dispatch serializeValue(Type signature, String property) {
1093 if (INSTANCE_IDENTIFIER == signature) {
1094 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1096 return '''«property»''';
1099 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1100 String propertyName) '''
1101 «type.resolvedName» «propertyName» = value.«propertyName»();
1102 if(«propertyName» != null) {
1103 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1104 java.util.Iterator _iterator = «propertyName».iterator();
1105 boolean _hasNext = _iterator.hasNext();
1107 Object _listItem = _iterator.next();
1108 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1109 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1110 _childNodes.add(_domValue);
1111 _hasNext = _iterator.hasNext();
1116 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1117 String propertyName) '''
1118 «type.resolvedName» «propertyName» = value.«propertyName»();
1119 if(«propertyName» != null) {
1120 java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1121 _childNodes.addAll(domValue);
1129 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1130 «type.resolvedName» «propertyName» = value.«propertyName»();
1131 if(«propertyName» != null) {
1132 Object domValue = «propertyName»;
1133 _childNodes.add(domValue);
1137 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1138 String propertyName) {
1139 serializeProperty(container, type.toInstance, propertyName)
1142 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1143 String propertyName) '''
1144 «type.resolvedName» «propertyName» = value.«propertyName»();
1145 if(«propertyName» != null) {
1146 Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1147 _childNodes.add(domValue);
1151 private def codecClassName(GeneratedType typeSpec) {
1152 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1155 private def codecClassName(Class typeSpec) {
1156 return '''«typeSpec.name»$Broker$Codec$DOM'''
1159 private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
1160 val ret = new HashMap<String, Type>();
1161 type.collectAllProperties(ret);
1165 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1166 for (definition : type.methodDefinitions) {
1167 set.put(definition.name, definition.returnType);
1169 for (property : type.properties) {
1170 set.put(property.getterName, property.returnType);
1172 for (parent : type.implements) {
1173 parent.collectAllProperties(set);
1177 def String getGetterName(GeneratedProperty property) {
1178 return "get" + property.name.toFirstUpper
1181 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1182 // NOOP for generic type.
1185 def String getResolvedName(Type type) {
1186 return type.asCtClass.name;
1189 def String getResolvedName(Class type) {
1190 return type.asCtClass.name;
1193 def CtClass asCtClass(Type type) {
1194 val name = type.fullyQualifiedName
1195 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1196 return cls.asCtClass;
1199 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1200 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1204 private def dispatch processException(Class<?> inputType, Exception e) {
1205 log.error("Cannot compile DOM Codec for {}", inputType, e);
1206 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1213 class PropertyPair {
1222 SchemaNode schemaNode;