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 return withClassLoaderAndLock(cls.classLoader,lock) [|
215 val valueTransformer = generateValueTransformer(cls, type);
216 return valueTransformer;
220 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
222 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
223 val properties = typeSpec.allProperties;
224 val ctCls = createClass(inputType.codecClassName) [
225 //staticField(Map,"AUGMENTATION_SERIALIZERS");
226 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
227 staticQNameField(node.QName);
228 implementsType(BINDING_CODEC)
229 method(Object, "toDomStatic", QName, Object) [
230 modifiers = PUBLIC + FINAL + STATIC
233 «QName.name» _resultName;
235 _resultName = «QName.name».create($1,QNAME.getLocalName());
239 java.util.List _childNodes = new java.util.ArrayList();
240 «inputType.resolvedName» value = («inputType.name») $2;
241 «FOR key : node.keyDefinition»
242 «val propertyName = key.getterName»
243 «val keyDef = node.getDataChildByName(key)»
244 «val property = properties.get(propertyName)»
245 «serializeProperty(keyDef, property, propertyName)»;
247 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
251 method(Object, "fromDomStatic", QName, Object) [
252 modifiers = PUBLIC + FINAL + STATIC
258 «QName.name» _localQName = $1;
259 java.util.Map _compositeNode = (java.util.Map) $2;
260 «FOR key : node.keyDefinition»
261 «val propertyName = key.getterName»
262 «val keyDef = node.getDataChildByName(key)»
263 «val property = properties.get(propertyName)»
264 «deserializeProperty(keyDef, property, propertyName)»;
266 «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
271 method(Object, "serialize", Object) [
274 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
275 «QName.name» _localQName = («QName.name») _input.getKey();
276 «inputType.name» _keyValue = («inputType.name») _input.getValue();
277 return toDomStatic(_localQName,_keyValue);
281 method(Object, "deserialize", Object) [
283 return fromDomStatic(QNAME,$1);
287 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
288 log.info("DOM Codec for {} was generated {}", inputType, ret)
289 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
290 } catch (Exception e) {
291 processException(inputType, e);
296 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
297 ChoiceCaseNode node) {
299 log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
300 val ctCls = createClass(type.codecClassName) [
301 //staticField(Map,"AUGMENTATION_SERIALIZERS");
302 implementsType(BINDING_CODEC)
303 staticQNameField(inputType);
304 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
305 staticField(it, AUGMENTATION_CODEC, BindingCodec)
306 method(Object, "toDomStatic", QName, Object) [
307 modifiers = PUBLIC + FINAL + STATIC
310 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
311 java.util.List _childNodes = new java.util.ArrayList();
312 «type.resolvedName» value = («type.resolvedName») $2;
313 «transformDataContainerBody(type.allProperties, node)»
314 return ($r) _childNodes;
318 method(Object, "serialize", Object) [
321 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
322 «QName.name» _localName = QNAME;
323 if(_input.getKey() != null) {
324 _localName = («QName.name») _input.getKey();
326 return toDomStatic(_localName,_input.getValue());
330 method(Object, "fromDomStatic", QName, Object) [
331 modifiers = PUBLIC + FINAL + STATIC
332 body = deserializeBody(type, node)
334 method(Object, "deserialize", Object) [
338 return fromDomStatic(QNAME,$1);
344 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
345 log.info("DOM Codec for {} was generated {}", inputType, ret)
346 return ret as Class<? extends BindingCodec<Object, Object>>;
347 } catch (Exception e) {
348 processException(inputType, e);
353 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
354 Class inputType, GeneratedType typeSpec, SchemaNode node) {
356 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
357 val ctCls = createClass(typeSpec.codecClassName) [
358 //staticField(Map,"AUGMENTATION_SERIALIZERS");
359 staticQNameField(inputType);
360 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
361 staticField(it, AUGMENTATION_CODEC, BindingCodec)
362 implementsType(BINDING_CODEC)
363 method(Object, "toDomStatic", QName, Object) [
364 modifiers = PUBLIC + FINAL + STATIC
365 body = serializeBodyFacade(typeSpec, node)
367 method(Object, "serialize", Object) [
370 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
371 «QName.name» _localName = QNAME;
372 if(_input.getKey() != null) {
373 _localName = («QName.name») _input.getKey();
375 return toDomStatic(_localName,_input.getValue());
379 method(Object, "fromDomStatic", QName, Object) [
380 modifiers = PUBLIC + FINAL + STATIC
381 body = deserializeBody(typeSpec, node)
383 method(Object, "deserialize", Object) [
385 return fromDomStatic(QNAME,$1);
390 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
391 listener?.onDataContainerCodecCreated(inputType, ret);
392 log.info("DOM Codec for {} was generated {}", inputType, ret)
394 } catch (Exception e) {
395 processException(inputType, e);
400 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
401 Class inputType, GeneratedType type, AugmentationSchema node) {
403 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
404 val properties = type.allProperties
405 val ctCls = createClass(type.codecClassName) [
406 //staticField(Map,"AUGMENTATION_SERIALIZERS");
407 staticQNameField(inputType);
408 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
409 staticField(it, AUGMENTATION_CODEC, BindingCodec)
410 implementsType(BINDING_CODEC)
411 method(Object, "toDomStatic", QName, Object) [
412 modifiers = PUBLIC + FINAL + STATIC
415 //System.out.println("Qname " + $1);
416 //System.out.println("Value " + $2);
417 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
418 java.util.List _childNodes = new java.util.ArrayList();
419 «type.resolvedName» value = («type.resolvedName») $2;
420 «FOR child : node.childNodes»
421 «var signature = properties.getFor(child)»
422 //System.out.println("«signature.key»" + value.«signature.key»());
423 «serializeProperty(child, signature.value, signature.key)»
425 return ($r) _childNodes;
429 method(Object, "serialize", Object) [
432 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
433 «QName.name» _localName = QNAME;
434 if(_input.getKey() != null) {
435 _localName = («QName.name») _input.getKey();
437 return toDomStatic(_localName,_input.getValue());
441 method(Object, "fromDomStatic", QName, Object) [
442 modifiers = PUBLIC + FINAL + STATIC
445 «QName.name» _localQName = QNAME;
450 java.util.Map _compositeNode = (java.util.Map) $2;
451 ////System.out.println(_localQName + " " + _compositeNode);
452 «type.builderName» _builder = new «type.builderName»();
453 «FOR child : node.childNodes»
454 «val signature = properties.getFor(child)»
455 «deserializeProperty(child, signature.value, signature.key)»
457 _builder.«signature.key.toSetter»(«signature.key»);
459 return _builder.build();
463 method(Object, "deserialize", Object) [
465 return fromDomStatic(QNAME,$1);
470 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
471 listener?.onDataContainerCodecCreated(inputType, ret);
473 } catch (Exception e) {
474 processException(inputType, e);
479 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
480 Class inputType, GeneratedType typeSpec, ChoiceNode node) {
482 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
483 val ctCls = createClass(typeSpec.codecClassName) [
484 //staticField(Map,"AUGMENTATION_SERIALIZERS");
485 //staticQNameField(inputType);
486 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
487 staticField(it, CLASS_TO_CASE_MAP, Map)
488 staticField(it, COMPOSITE_TO_CASE, Map)
489 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
490 implementsType(BINDING_CODEC)
491 method(List, "toDomStatic", QName, Object) [
492 modifiers = PUBLIC + FINAL + STATIC
498 «DataObject.name» _baValue = («DataObject.name») $2;
499 Class _baClass = _baValue.getImplementedInterface();
500 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
504 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
505 return (java.util.List) _codec.serialize(_input);
509 method(Object, "serialize", Object) [
511 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
514 method(Object, "fromDomStatic", QName, Map) [
515 modifiers = PUBLIC + FINAL + STATIC
518 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
520 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
526 method(Object, "deserialize", Object) [
528 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
533 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
534 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
535 listener?.onChoiceCodecCreated(inputType, ret);
536 log.info("DOM Codec for {} was generated {}", inputType, ret)
538 } catch (Exception e) {
539 processException(inputType, e);
544 private def keyConstructorList(List<QName> qnames) {
545 val names = new TreeSet<String>()
546 for (name : qnames) {
547 val fieldName = name.getterName;
548 names.add(fieldName);
550 return Joiner.on(",").join(names);
553 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
554 val ret = serializeBody(type, node);
558 private def String deserializeBody(GeneratedType type, SchemaNode node) {
559 val ret = deserializeBodyImpl(type, node);
563 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
564 if (node.keyDefinition != null && !node.keyDefinition.empty) {
566 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
567 _builder.setKey(getKey);
572 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
574 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
579 java.util.Map _compositeNode = (java.util.Map) $2;
580 «type.builderName» _builder = new «type.builderName»();
581 return _builder.build();
585 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
587 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
591 java.util.Map _compositeNode = (java.util.Map) $2;
592 «type.builderName» _builder = new «type.builderName»();
593 «deserializeKey(type, node)»
594 «deserializeDataNodeContainerBody(type, node)»
595 «deserializeAugmentations»
596 return _builder.build();
600 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
602 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
606 java.util.Map _compositeNode = (java.util.Map) $2;
607 «type.builderName» _builder = new «type.builderName»();
608 «deserializeDataNodeContainerBody(type, node)»
609 «deserializeAugmentations»
610 return _builder.build();
614 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
616 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
621 java.util.Map _compositeNode = (java.util.Map) $2;
622 ////System.out.println(_localQName + " " + _compositeNode);
623 «type.builderName» _builder = new «type.builderName»();
624 «deserializeDataNodeContainerBody(type, node)»
625 «deserializeAugmentations»
626 return _builder.build();
630 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
631 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
634 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
635 DataNodeContainer node) {
637 «FOR child : node.childNodes.filter[!augmenting]»
638 «val signature = properties.getFor(child)»
639 «deserializeProperty(child, signature.value, signature.key)»
641 _builder.«signature.key.toSetter»(«signature.key»);
647 def deserializeAugmentations() '''
648 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
649 if(_augmentation != null) {
650 «Iterator.name» _entries = _augmentation.entrySet().iterator();
651 while(_entries.hasNext()) {
652 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
653 //System.out.println("Aug. key:" + _entry.getKey());
654 Class _type = (Class) _entry.getKey();
655 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
656 _builder.addAugmentation(_type,_value);
661 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
662 String propertyName) '''
663 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
665 ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
666 java.util.List «propertyName» = new java.util.ArrayList();
667 if(_dom_«propertyName» != null) {
668 java.util.List _serialized = new java.util.ArrayList();
669 java.util.Iterator _iterator = _dom_«propertyName».iterator();
670 boolean _hasNext = _iterator.hasNext();
672 Object _listItem = _iterator.next();
673 ////System.out.println(" item" + _listItem);
674 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
675 ////System.out.println(" value" + _value);
676 «propertyName».add(_value);
677 _hasNext = _iterator.hasNext();
681 ////System.out.println(" list" + «propertyName»);
684 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
685 String propertyName) '''
686 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
688 java.util.List «propertyName» = new java.util.ArrayList();
689 if(_dom_«propertyName» != null) {
690 java.util.List _serialized = new java.util.ArrayList();
691 java.util.Iterator _iterator = _dom_«propertyName».iterator();
692 boolean _hasNext = _iterator.hasNext();
694 Object _listItem = _iterator.next();
695 if(_listItem instanceof java.util.Map.Entry) {
696 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
697 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
698 «propertyName».add(_value);
700 _hasNext = _iterator.hasNext();
705 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
706 java.util.List _dom_«propertyName»_list =
707 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
708 «type.resolvedName» «propertyName» = null;
709 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
710 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
711 Object _inner_value = _dom_«propertyName».getValue();
712 «propertyName» = «deserializeValue(type, "_inner_value")»;
716 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
717 String propertyName) '''
718 java.util.List _dom_«propertyName»_list =
719 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
720 «type.resolvedName» «propertyName» = null;
721 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
723 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
724 «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
728 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
729 «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
732 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
733 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
736 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
737 Class<?> inputType, GeneratedTransferObject typeSpec) {
740 val returnType = typeSpec.valueReturnType;
741 if (returnType == null) {
742 val ctCls = createDummyImplementation(inputType, typeSpec);
743 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
744 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
746 var hasBinding = false;
748 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
750 } catch (ClassNotFoundException e) {
753 val hasYangBinding = hasBinding
754 val ctCls = createClass(typeSpec.codecClassName) [
755 //staticField(Map,"AUGMENTATION_SERIALIZERS");
757 implementsType(BINDING_CODEC)
758 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
759 implementsType(BindingDeserializer.asCtClass)
761 method(Object, "toDomValue", Object) [
762 modifiers = PUBLIC + FINAL + STATIC
765 ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
770 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
771 ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
772 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
773 ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
774 Object _domValue = «serializeValue(returnType, "_value")»;
779 method(Object, "serialize", Object) [
782 return toDomValue($1);
786 method(Object, "fromDomValue", Object) [
787 modifiers = PUBLIC + FINAL + STATIC
790 ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
795 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
796 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
801 method(Object, "deserialize", Object) [
803 return fromDomValue($1);
809 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
810 log.info("DOM Codec for {} was generated {}", inputType, ret)
811 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
812 } catch (Exception e) {
813 log.error("Cannot compile DOM Codec for {}", inputType, e);
814 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
815 exception.addSuppressed(e);
821 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
822 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
823 return createClass(typeSpec.codecClassName) [
824 //staticField(Map,"AUGMENTATION_SERIALIZERS");
825 implementsType(BINDING_CODEC)
826 implementsType(BindingDeserializer.asCtClass)
827 method(Object, "toDomValue", Object) [
828 modifiers = PUBLIC + FINAL + STATIC
829 body = '''return null;'''
831 method(Object, "serialize", Object) [
834 return toDomValue($1);
838 method(Object, "fromDomValue", Object) [
839 modifiers = PUBLIC + FINAL + STATIC
840 body = '''return null;'''
842 method(Object, "deserialize", Object) [
844 return fromDomValue($1);
851 private def Type getValueReturnType(GeneratedTransferObject object) {
852 for (prop : object.properties) {
853 if (prop.name == "value") {
854 return prop.returnType;
857 if (object.superType != null) {
858 return getValueReturnType(object.superType);
863 private def dispatch Class<?> generateValueTransformer(
864 Class<?> inputType, Enumeration typeSpec) {
866 log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
867 val ctCls = createClass(typeSpec.codecClassName) [
868 //staticField(Map,"AUGMENTATION_SERIALIZERS");
869 //implementsType(BINDING_CODEC)
871 method(Object, "toDomValue", Object) [
872 modifiers = PUBLIC + FINAL + STATIC
877 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
878 return _value.getValue();
881 method(Object, "serialize", Object) [
883 return toDomValue($1);
886 method(Object, "fromDomValue", Object) [
887 modifiers = PUBLIC + FINAL + STATIC
893 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
897 method(Object, "deserialize", Object) [
899 return fromDomValue($1);
904 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
905 log.info("DOM Codec for {} was generated {}", inputType, ret)
907 } catch (CodeGenerationException e) {
908 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
909 } catch (Exception e) {
910 log.error("Cannot compile DOM Codec for {}", inputType, e);
911 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
912 exception.addSuppressed(e);
918 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
919 val cls = newClass.toClass(loader, domain);
920 if (classFileCapturePath !== null) {
921 newClass.writeFile(classFileCapturePath.absolutePath);
923 listener?.onCodecCreated(cls);
927 def debugWriteClass(CtClass class1) {
928 val path = class1.name.replace(".", "/") + ".class"
930 val captureFile = new File(classFileCapturePath, path);
931 captureFile.createNewFile
935 private def dispatch String deserializeValue(Type type, String domParameter) {
936 if (INSTANCE_IDENTIFIER.equals(type)) {
938 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
941 return '''(«type.resolvedName») «domParameter»'''
949 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
950 «type.resolvedName» «propertyName» = null;
953 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
954 String propertyName) {
955 _deserializeProperty(container, type.toInstance, propertyName)
958 public static def toSetter(String it) {
960 if (startsWith("is")) {
961 return "set" + substring(2);
962 } else if (startsWith("get")) {
963 return "set" + substring(3);
969 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
970 «type.resolvedName» «propertyName» = value.«propertyName»();
971 if(«propertyName» != null) {
972 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
973 _childNodes.add(domValue);
977 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
979 private def staticQNameField(CtClass it, Class<?> node) {
980 val field = new CtField(ctQName, "QNAME", it);
981 field.modifiers = PUBLIC + FINAL + STATIC;
982 addField(field, '''«node.name».QNAME''')
985 private def staticQNameField(CtClass it, QName node) {
986 val field = new CtField(ctQName, "QNAME", it);
987 field.modifiers = PUBLIC + FINAL + STATIC;
989 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
992 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
994 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
995 java.util.List _childNodes = new java.util.ArrayList();
996 «type.resolvedName» value = («type.resolvedName») $2;
997 «transformDataContainerBody(type.allProperties, node)»
998 «serializeAugmentations»
999 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1003 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
1005 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1006 java.util.List _childNodes = new java.util.ArrayList();
1007 «type.resolvedName» value = («type.resolvedName») $2;
1008 «transformDataContainerBody(type.allProperties, node)»
1009 «serializeAugmentations»
1010 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1014 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1016 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1017 java.util.List _childNodes = new java.util.ArrayList();
1018 «type.resolvedName» value = («type.resolvedName») $2;
1019 «transformDataContainerBody(type.allProperties, node)»
1020 «serializeAugmentations»
1021 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1025 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1027 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1028 java.util.List _childNodes = new java.util.ArrayList();
1029 «type.resolvedName» value = («type.resolvedName») $2;
1030 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1034 private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
1036 «FOR child : node.childNodes.filter[!augmenting]»
1037 «var signature = properties.getFor(child)»
1038 //System.out.println("«signature.key»" + value.«signature.key»());
1039 «serializeProperty(child, signature.value, signature.key)»
1045 def serializeAugmentations() '''
1046 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1047 if(_augmentations != null) {
1048 _childNodes.addAll(_augmentations);
1052 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1053 val sig = map.get(node.getterName);
1056 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1058 return new SimpleEntry(node.getterName, sig);
1061 private static def String getBooleanGetterName(DataSchemaNode node) {
1062 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1065 private static def String getGetterName(DataSchemaNode node) {
1066 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1069 private static def String getGetterName(QName node) {
1070 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1073 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1074 String propertyName) '''
1075 «type.resolvedName» «propertyName» = value.«propertyName»();
1076 if(«propertyName» != null) {
1077 java.util.Iterator _iterator = «propertyName».iterator();
1078 boolean _hasNext = _iterator.hasNext();
1080 Object _listItem = _iterator.next();
1081 Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
1082 _childNodes.add(_domValue);
1083 _hasNext = _iterator.hasNext();
1088 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1089 «type.resolvedName» «propertyName» = value.«propertyName»();
1091 if(«propertyName» != null) {
1092 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1093 Object _propValue = «serializeValue(type, propertyName)»;
1094 if(_propValue != null) {
1095 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1096 _childNodes.add(_domValue);
1101 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1102 resolvedName».toDomValue(«parameter»)'''
1104 private def dispatch serializeValue(Type signature, String property) {
1105 if (INSTANCE_IDENTIFIER == signature) {
1106 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1108 return '''«property»''';
1111 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1112 String propertyName) '''
1113 «type.resolvedName» «propertyName» = value.«propertyName»();
1114 if(«propertyName» != null) {
1115 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1116 java.util.Iterator _iterator = «propertyName».iterator();
1117 boolean _hasNext = _iterator.hasNext();
1119 Object _listItem = _iterator.next();
1120 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1121 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1122 _childNodes.add(_domValue);
1123 _hasNext = _iterator.hasNext();
1128 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1129 String propertyName) '''
1130 «type.resolvedName» «propertyName» = value.«propertyName»();
1131 if(«propertyName» != null) {
1132 java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1133 _childNodes.addAll(domValue);
1141 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1142 «type.resolvedName» «propertyName» = value.«propertyName»();
1143 if(«propertyName» != null) {
1144 Object domValue = «propertyName»;
1145 _childNodes.add(domValue);
1149 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1150 String propertyName) {
1151 serializeProperty(container, type.toInstance, propertyName)
1154 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1155 String propertyName) '''
1156 «type.resolvedName» «propertyName» = value.«propertyName»();
1157 if(«propertyName» != null) {
1158 Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1159 _childNodes.add(domValue);
1163 private def codecClassName(GeneratedType typeSpec) {
1164 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1167 private def codecClassName(Class typeSpec) {
1168 return '''«typeSpec.name»$Broker$Codec$DOM'''
1171 private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
1172 val ret = new HashMap<String, Type>();
1173 type.collectAllProperties(ret);
1177 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1178 for (definition : type.methodDefinitions) {
1179 set.put(definition.name, definition.returnType);
1181 for (property : type.properties) {
1182 set.put(property.getterName, property.returnType);
1184 for (parent : type.implements) {
1185 parent.collectAllProperties(set);
1189 def String getGetterName(GeneratedProperty property) {
1190 return "get" + property.name.toFirstUpper
1193 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1194 // NOOP for generic type.
1197 def String getResolvedName(Type type) {
1198 return type.asCtClass.name;
1201 def String getResolvedName(Class type) {
1202 return type.asCtClass.name;
1205 def CtClass asCtClass(Type type) {
1206 val name = type.fullyQualifiedName
1207 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1208 return cls.asCtClass;
1211 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1212 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1216 private def dispatch processException(Class<?> inputType, Exception e) {
1217 log.error("Cannot compile DOM Codec for {}", inputType, e);
1218 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1225 class PropertyPair {
1234 SchemaNode schemaNode;