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 listener.onClassProcessed(inputType);
99 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
101 val ref = Types.typeForClass(inputType)
102 val node = typeToSchemaNode.get(ref)
103 val typeSpecBuilder = typeToDefinition.get(ref)
104 val typeSpec = typeSpecBuilder.toInstance();
105 val newret = generateTransformerFor(inputType, typeSpec, node);
106 listener.onClassProcessed(inputType);
107 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
111 def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
112 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
113 val ret = getGeneratedClass(inputType)
115 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
117 val ref = Types.typeForClass(inputType)
118 val node = typeToAugmentation.get(ref)
119 val typeSpecBuilder = typeToDefinition.get(ref)
120 val typeSpec = typeSpecBuilder.toInstance();
121 val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
122 listener.onClassProcessed(inputType);
123 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
127 def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
128 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
129 val ret = getGeneratedClass(inputType)
131 return ret as Class<? extends BindingCodec<Object, Object>>;
133 val ref = Types.typeForClass(inputType)
134 val typeSpecBuilder = typeToDefinition.get(ref)
135 val typeSpec = typeSpecBuilder.toInstance();
136 val newret = generateCaseCodec(inputType, typeSpec, node);
137 return newret as Class<? extends BindingCodec<Object, Object>>;
141 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
142 return withClassLoaderAndLock(parentType.classLoader, lock) [ |
143 val inputName = parentType.name + "Key";
144 val inputType = loadClassWithTCCL(inputName);
145 val ret = getGeneratedClass(inputType)
147 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
149 val ref = Types.typeForClass(parentType)
150 val node = typeToSchemaNode.get(ref) as ListSchemaNode
151 val typeSpecBuilder = typeToDefinition.get(ref)
152 val typeSpec = typeSpecBuilder.identifierDefinition;
153 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
154 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
158 def getIdentifierDefinition(GeneratedTypeBuilder builder) {
159 val inst = builder.toInstance
160 val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
161 return keyMethod.returnType as GeneratedTransferObject
164 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
165 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
166 val ret = getGeneratedClass(inputType)
168 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
170 val ref = Types.typeForClass(inputType)
171 val node = typeToSchemaNode.get(ref) as ListSchemaNode
172 val typeSpecBuilder = typeToDefinition.get(ref)
173 val typeSpec = typeSpecBuilder.toInstance();
174 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
175 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
179 private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
180 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
181 val transformer = getGeneratedClass(inputType)
182 if (transformer != null) {
185 val newret = generateKeyTransformerFor(inputType, type, schema);
186 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
190 private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
193 return loadClassWithTCCL(cls.codecClassName)
194 } catch (ClassNotFoundException e) {
199 private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
200 val cls = loadClassWithTCCL(type.resolvedName + "Key");
201 keyTransformerFor(cls, type, node);
204 private def serializer(Type type) {
205 val cls = loadClassWithTCCL(type.resolvedName);
211 private def Class<?> getValueSerializer(GeneratedTransferObject type) {
212 val cls = loadClassWithTCCL(type.resolvedName);
213 val transformer = cls.generatedClass;
214 if (transformer !== null) {
217 return withClassLoaderAndLock(cls.classLoader,lock) [|
218 val valueTransformer = generateValueTransformer(cls, type);
219 return valueTransformer;
223 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
225 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
226 val properties = typeSpec.allProperties;
227 val ctCls = createClass(inputType.codecClassName) [
228 //staticField(Map,"AUGMENTATION_SERIALIZERS");
229 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
230 staticQNameField(node.QName);
231 implementsType(BINDING_CODEC)
232 method(Object, "toDomStatic", QName, Object) [
233 modifiers = PUBLIC + FINAL + STATIC
236 «QName.name» _resultName;
238 _resultName = «QName.name».create($1,QNAME.getLocalName());
242 java.util.List _childNodes = new java.util.ArrayList();
243 «inputType.resolvedName» value = («inputType.name») $2;
244 «FOR key : node.keyDefinition»
245 «val propertyName = key.getterName»
246 «val keyDef = node.getDataChildByName(key)»
247 «val property = properties.get(propertyName)»
248 «serializeProperty(keyDef, property, propertyName)»;
250 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
254 method(Object, "fromDomStatic", QName, Object) [
255 modifiers = PUBLIC + FINAL + STATIC
261 «QName.name» _localQName = $1;
262 java.util.Map _compositeNode = (java.util.Map) $2;
263 «FOR key : node.keyDefinition»
264 «val propertyName = key.getterName»
265 «val keyDef = node.getDataChildByName(key)»
266 «val property = properties.get(propertyName)»
267 «deserializeProperty(keyDef, property, propertyName)»;
269 «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
274 method(Object, "serialize", Object) [
277 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
278 «QName.name» _localQName = («QName.name») _input.getKey();
279 «inputType.name» _keyValue = («inputType.name») _input.getValue();
280 return toDomStatic(_localQName,_keyValue);
284 method(Object, "deserialize", Object) [
286 return fromDomStatic(QNAME,$1);
290 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
291 log.info("DOM Codec for {} was generated {}", inputType, ret)
292 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
293 } catch (Exception e) {
294 processException(inputType, e);
299 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
300 ChoiceCaseNode node) {
302 //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
303 val ctCls = createClass(type.codecClassName) [
304 //staticField(Map,"AUGMENTATION_SERIALIZERS");
305 implementsType(BINDING_CODEC)
306 staticQNameField(inputType);
307 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
308 staticField(it, AUGMENTATION_CODEC, BindingCodec)
309 method(Object, "toDomStatic", QName, Object) [
310 modifiers = PUBLIC + FINAL + STATIC
313 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
314 java.util.List _childNodes = new java.util.ArrayList();
315 «type.resolvedName» value = («type.resolvedName») $2;
316 «transformDataContainerBody(type,type.allProperties, node)»
317 return ($r) _childNodes;
321 method(Object, "serialize", Object) [
324 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
325 «QName.name» _localName = QNAME;
326 if(_input.getKey() != null) {
327 _localName = («QName.name») _input.getKey();
329 return toDomStatic(_localName,_input.getValue());
333 method(Object, "fromDomStatic", QName, Object) [
334 modifiers = PUBLIC + FINAL + STATIC
335 body = deserializeBody(type, node)
337 method(Object, "deserialize", Object) [
341 return fromDomStatic(QNAME,$1);
347 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
348 log.info("DOM Codec for {} was generated {}", inputType, ret)
349 return ret as Class<? extends BindingCodec<Object, Object>>;
350 } catch (Exception e) {
351 processException(inputType, e);
356 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
357 Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
359 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
360 val ctCls = createClass(typeSpec.codecClassName) [
361 //staticField(Map,"AUGMENTATION_SERIALIZERS");
362 staticQNameField(inputType);
363 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
364 staticField(it, AUGMENTATION_CODEC, BindingCodec)
365 implementsType(BINDING_CODEC)
366 method(Object, "toDomStatic", QName, Object) [
367 modifiers = PUBLIC + FINAL + STATIC
368 body = serializeBodyFacade(typeSpec, node)
370 method(Object, "serialize", Object) [
373 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
374 «QName.name» _localName = QNAME;
375 if(_input.getKey() != null) {
376 _localName = («QName.name») _input.getKey();
378 return toDomStatic(_localName,_input.getValue());
382 method(Object, "fromDomStatic", QName, Object) [
383 modifiers = PUBLIC + FINAL + STATIC
384 body = deserializeBody(typeSpec, node)
386 method(Object, "deserialize", Object) [
388 return fromDomStatic(QNAME,$1);
393 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
394 listener?.onDataContainerCodecCreated(inputType, ret);
395 log.info("DOM Codec for {} was generated {}", inputType, ret)
397 } catch (Exception e) {
398 processException(inputType, e);
403 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
404 Class<?> inputType, GeneratedType type, AugmentationSchema node) {
406 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
407 val properties = type.allProperties
408 val ctCls = createClass(type.codecClassName) [
409 //staticField(Map,"AUGMENTATION_SERIALIZERS");
410 staticQNameField(inputType);
411 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
412 staticField(it, AUGMENTATION_CODEC, BindingCodec)
413 implementsType(BINDING_CODEC)
414 method(Object, "toDomStatic", QName, Object) [
415 modifiers = PUBLIC + FINAL + STATIC
418 //System.out.println("Qname " + $1);
419 //System.out.println("Value " + $2);
420 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
421 java.util.List _childNodes = new java.util.ArrayList();
422 «type.resolvedName» value = («type.resolvedName») $2;
423 «FOR child : node.childNodes»
424 «var signature = properties.getFor(child)»
425 //System.out.println("«signature.key»" + value.«signature.key»());
426 «serializeProperty(child, signature.value, signature.key)»
428 return ($r) _childNodes;
432 method(Object, "serialize", Object) [
435 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
436 «QName.name» _localName = QNAME;
437 if(_input.getKey() != null) {
438 _localName = («QName.name») _input.getKey();
440 return toDomStatic(_localName,_input.getValue());
444 method(Object, "fromDomStatic", QName, Object) [
445 modifiers = PUBLIC + FINAL + STATIC
448 «QName.name» _localQName = QNAME;
453 java.util.Map _compositeNode = (java.util.Map) $2;
454 //System.out.println(_localQName + " " + _compositeNode);
455 «type.builderName» _builder = new «type.builderName»();
456 «FOR child : node.childNodes»
457 «val signature = properties.getFor(child)»
458 «deserializeProperty(child, signature.value, signature.key)»
460 _builder.«signature.key.toSetter»(«signature.key»);
462 return _builder.build();
466 method(Object, "deserialize", Object) [
468 return fromDomStatic(QNAME,$1);
473 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
474 listener?.onDataContainerCodecCreated(inputType, ret);
476 } catch (Exception e) {
477 processException(inputType, e);
482 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
483 Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
485 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
486 val ctCls = createClass(typeSpec.codecClassName) [
487 //staticField(Map,"AUGMENTATION_SERIALIZERS");
488 //staticQNameField(inputType);
489 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
490 staticField(it, CLASS_TO_CASE_MAP, Map)
491 staticField(it, COMPOSITE_TO_CASE, Map)
492 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
493 implementsType(BINDING_CODEC)
494 method(List, "toDomStatic", QName, Object) [
495 modifiers = PUBLIC + FINAL + STATIC
501 «DataObject.name» _baValue = («DataObject.name») $2;
502 Class _baClass = _baValue.getImplementedInterface();
503 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
507 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
508 Object _ret = _codec.serialize(_input);
509 //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
510 return («List.name») _ret;
514 method(Object, "serialize", Object) [
516 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
519 method(Object, "fromDomStatic", QName, Map) [
520 modifiers = PUBLIC + FINAL + STATIC
523 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
525 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
531 method(Object, "deserialize", Object) [
533 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
538 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
539 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
540 listener?.onChoiceCodecCreated(inputType, ret);
541 log.info("DOM Codec for {} was generated {}", inputType, ret)
543 } catch (Exception e) {
544 processException(inputType, e);
549 private def keyConstructorList(List<QName> qnames) {
550 val names = new TreeSet<String>()
551 for (name : qnames) {
552 val fieldName = name.getterName;
553 names.add(fieldName);
555 return Joiner.on(",").join(names);
558 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
559 val ret = serializeBody(type, node);
563 private def String deserializeBody(GeneratedType type, SchemaNode node) {
564 val ret = deserializeBodyImpl(type, node);
568 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
569 if (node.keyDefinition != null && !node.keyDefinition.empty) {
571 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
572 _builder.setKey(getKey);
577 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
579 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
584 java.util.Map _compositeNode = (java.util.Map) $2;
585 «type.builderName» _builder = new «type.builderName»();
586 return _builder.build();
590 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
592 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
596 java.util.Map _compositeNode = (java.util.Map) $2;
597 «type.builderName» _builder = new «type.builderName»();
598 «deserializeKey(type, node)»
599 «deserializeDataNodeContainerBody(type, node)»
600 «deserializeAugmentations»
601 return _builder.build();
605 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
607 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
611 java.util.Map _compositeNode = (java.util.Map) $2;
612 «type.builderName» _builder = new «type.builderName»();
613 «deserializeDataNodeContainerBody(type, node)»
614 «deserializeAugmentations»
615 return _builder.build();
619 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
621 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
626 java.util.Map _compositeNode = (java.util.Map) $2;
627 //System.out.println(_localQName + " " + _compositeNode);
628 «type.builderName» _builder = new «type.builderName»();
629 «deserializeDataNodeContainerBody(type, node)»
630 «deserializeAugmentations»
631 return _builder.build();
635 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
636 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
639 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
640 DataNodeContainer node) {
642 «FOR child : node.childNodes.filter[!augmenting]»
643 «val signature = properties.getFor(child)»
644 «deserializeProperty(child, signature.value, signature.key)»
646 _builder.«signature.key.toSetter»(«signature.key»);
652 def deserializeAugmentations() '''
653 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
654 if(_augmentation != null) {
655 «Iterator.name» _entries = _augmentation.entrySet().iterator();
656 while(_entries.hasNext()) {
657 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
658 //System.out.println("Aug. key:" + _entry.getKey());
659 Class _type = (Class) _entry.getKey();
660 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
661 _builder.addAugmentation(_type,_value);
666 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
667 String propertyName) '''
668 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
670 //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
671 java.util.List «propertyName» = new java.util.ArrayList();
672 if(_dom_«propertyName» != null) {
673 java.util.List _serialized = new java.util.ArrayList();
674 java.util.Iterator _iterator = _dom_«propertyName».iterator();
675 boolean _hasNext = _iterator.hasNext();
677 Object _listItem = _iterator.next();
678 //System.out.println(" item" + _listItem);
679 Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
680 //System.out.println(" value" + _value);
681 «propertyName».add(_value);
682 _hasNext = _iterator.hasNext();
686 //System.out.println(" list" + «propertyName»);
689 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
690 String propertyName) '''
691 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
693 java.util.List «propertyName» = new java.util.ArrayList();
694 if(_dom_«propertyName» != null) {
695 java.util.List _serialized = new java.util.ArrayList();
696 java.util.Iterator _iterator = _dom_«propertyName».iterator();
697 boolean _hasNext = _iterator.hasNext();
699 Object _listItem = _iterator.next();
700 if(_listItem instanceof java.util.Map.Entry) {
701 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
702 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
703 «propertyName».add(_value);
705 _hasNext = _iterator.hasNext();
710 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
711 java.util.List _dom_«propertyName»_list =
712 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
713 «type.resolvedName» «propertyName» = null;
714 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
715 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
716 Object _inner_value = _dom_«propertyName».getValue();
717 «propertyName» = «deserializeValue(type, "_inner_value")»;
721 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
722 String propertyName) '''
723 java.util.List _dom_«propertyName»_list =
724 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
725 «type.resolvedName» «propertyName» = null;
726 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
728 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
729 «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
733 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
734 «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
737 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
738 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
741 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
742 Class<?> inputType, GeneratedTransferObject typeSpec) {
745 val returnType = typeSpec.valueReturnType;
746 if (returnType == null) {
747 val ctCls = createDummyImplementation(inputType, typeSpec);
748 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
749 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
751 var hasBinding = false;
753 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
754 hasBinding = bindingCodecClass !== null;
755 } catch (ClassNotFoundException e) {
758 val hasYangBinding = hasBinding
759 val ctCls = createClass(typeSpec.codecClassName) [
760 //staticField(Map,"AUGMENTATION_SERIALIZERS");
762 implementsType(BINDING_CODEC)
763 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
764 implementsType(BindingDeserializer.asCtClass)
766 method(Object, "toDomValue", Object) [
767 modifiers = PUBLIC + FINAL + STATIC
770 //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
775 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
776 //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
777 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
778 //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
779 Object _domValue = «serializeValue(returnType, "_value")»;
784 method(Object, "serialize", Object) [
787 return toDomValue($1);
791 method(Object, "fromDomValue", Object) [
792 modifiers = PUBLIC + FINAL + STATIC
795 //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
800 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
801 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
806 method(Object, "deserialize", Object) [
808 return fromDomValue($1);
814 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
815 log.info("DOM Codec for {} was generated {}", inputType, ret)
816 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
817 } catch (Exception e) {
818 log.error("Cannot compile DOM Codec for {}", inputType, e);
819 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
820 exception.addSuppressed(e);
826 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
827 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
828 return createClass(typeSpec.codecClassName) [
829 //staticField(Map,"AUGMENTATION_SERIALIZERS");
830 implementsType(BINDING_CODEC)
831 implementsType(BindingDeserializer.asCtClass)
832 method(Object, "toDomValue", Object) [
833 modifiers = PUBLIC + FINAL + STATIC
834 body = '''return null;'''
836 method(Object, "serialize", Object) [
839 return toDomValue($1);
843 method(Object, "fromDomValue", Object) [
844 modifiers = PUBLIC + FINAL + STATIC
845 body = '''return null;'''
847 method(Object, "deserialize", Object) [
849 return fromDomValue($1);
856 private def Type getValueReturnType(GeneratedTransferObject object) {
857 for (prop : object.properties) {
858 if (prop.name == "value") {
859 return prop.returnType;
862 if (object.superType != null) {
863 return getValueReturnType(object.superType);
868 private def dispatch Class<?> generateValueTransformer(
869 Class<?> inputType, Enumeration typeSpec) {
871 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
872 val ctCls = createClass(typeSpec.codecClassName) [
873 //staticField(Map,"AUGMENTATION_SERIALIZERS");
874 //implementsType(BINDING_CODEC)
876 method(Object, "toDomValue", Object) [
877 modifiers = PUBLIC + FINAL + STATIC
882 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
883 return _value.getValue();
886 method(Object, "serialize", Object) [
888 return toDomValue($1);
891 method(Object, "fromDomValue", Object) [
892 modifiers = PUBLIC + FINAL + STATIC
898 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null);
902 method(Object, "deserialize", Object) [
904 return fromDomValue($1);
909 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
910 log.info("DOM Codec for {} was generated {}", inputType, ret)
912 } catch (CodeGenerationException e) {
913 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
914 } catch (Exception e) {
915 log.error("Cannot compile DOM Codec for {}", inputType, e);
916 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
917 exception.addSuppressed(e);
923 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
924 val cls = newClass.toClass(loader, domain);
925 if (classFileCapturePath !== null) {
926 newClass.writeFile(classFileCapturePath.absolutePath);
928 listener?.onCodecCreated(cls);
932 def debugWriteClass(CtClass class1) {
933 val path = class1.name.replace(".", "/") + ".class"
935 val captureFile = new File(classFileCapturePath, path);
936 captureFile.createNewFile
940 private def dispatch String deserializeValue(Type type, String domParameter) {
941 if (INSTANCE_IDENTIFIER.equals(type)) {
943 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
946 return '''(«type.resolvedName») «domParameter»'''
954 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
955 «type.resolvedName» «propertyName» = null;
958 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
959 String propertyName) {
960 _deserializeProperty(container, type.toInstance, propertyName)
963 public static def toSetter(String it) {
965 if (startsWith("is")) {
966 return "set" + substring(2);
967 } else if (startsWith("get")) {
968 return "set" + substring(3);
974 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
975 «type.resolvedName» «propertyName» = value.«propertyName»();
976 if(«propertyName» != null) {
977 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
978 _childNodes.add(domValue);
982 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
984 private def staticQNameField(CtClass it, Class<?> node) {
985 val field = new CtField(ctQName, "QNAME", it);
986 field.modifiers = PUBLIC + FINAL + STATIC;
987 addField(field, '''«node.name».QNAME''')
990 private def staticQNameField(CtClass it, QName node) {
991 val field = new CtField(ctQName, "QNAME", it);
992 field.modifiers = PUBLIC + FINAL + STATIC;
994 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
997 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
999 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1000 java.util.List _childNodes = new java.util.ArrayList();
1001 «type.resolvedName» value = («type.resolvedName») $2;
1002 «transformDataContainerBody(type,type.allProperties, node)»
1003 «serializeAugmentations»
1004 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1008 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
1010 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1011 java.util.List _childNodes = new java.util.ArrayList();
1012 «type.resolvedName» value = («type.resolvedName») $2;
1013 «transformDataContainerBody(type,type.allProperties, node)»
1014 «serializeAugmentations»
1015 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1019 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1021 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1022 java.util.List _childNodes = new java.util.ArrayList();
1023 «type.resolvedName» value = («type.resolvedName») $2;
1024 «transformDataContainerBody(type,type.allProperties, node)»
1025 «serializeAugmentations»
1026 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1030 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1032 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1033 java.util.List _childNodes = new java.util.ArrayList();
1034 «type.resolvedName» value = («type.resolvedName») $2;
1035 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1039 private def transformDataContainerBody(Type type,Map<String, Type> properties, DataNodeContainer node) {
1041 «FOR child : node.childNodes.filter[!augmenting]»
1042 «var signature = properties.getFor(child)»
1043 //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
1044 «serializeProperty(child, signature.value, signature.key)»
1050 def serializeAugmentations() '''
1051 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1052 if(_augmentations != null) {
1053 _childNodes.addAll(_augmentations);
1057 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1058 val sig = map.get(node.getterName);
1061 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1063 return new SimpleEntry(node.getterName, sig);
1066 private static def String getBooleanGetterName(DataSchemaNode node) {
1067 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1070 private static def String getGetterName(DataSchemaNode node) {
1071 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1074 private static def String getGetterName(QName node) {
1075 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1078 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1079 String propertyName) '''
1080 «type.resolvedName» «propertyName» = value.«propertyName»();
1081 if(«propertyName» != null) {
1082 java.util.Iterator _iterator = «propertyName».iterator();
1083 boolean _hasNext = _iterator.hasNext();
1085 Object _listItem = _iterator.next();
1086 Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
1087 _childNodes.add(_domValue);
1088 _hasNext = _iterator.hasNext();
1093 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1094 «type.resolvedName» «propertyName» = value.«propertyName»();
1096 if(«propertyName» != null) {
1097 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1098 Object _propValue = «serializeValue(type, propertyName)»;
1099 if(_propValue != null) {
1100 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1101 _childNodes.add(_domValue);
1106 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1107 resolvedName».toDomValue(«parameter»)'''
1109 private def dispatch serializeValue(Type signature, String property) {
1110 if (INSTANCE_IDENTIFIER == signature) {
1111 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1113 return '''«property»''';
1116 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1117 String propertyName) '''
1118 «type.resolvedName» «propertyName» = value.«propertyName»();
1119 if(«propertyName» != null) {
1120 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1121 java.util.Iterator _iterator = «propertyName».iterator();
1122 boolean _hasNext = _iterator.hasNext();
1124 Object _listItem = _iterator.next();
1125 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1126 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1127 _childNodes.add(_domValue);
1128 _hasNext = _iterator.hasNext();
1133 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1134 String propertyName) '''
1135 «type.resolvedName» «propertyName» = value.«propertyName»();
1136 if(«propertyName» != null) {
1137 java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1138 _childNodes.addAll(domValue);
1146 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1147 «type.resolvedName» «propertyName» = value.«propertyName»();
1148 if(«propertyName» != null) {
1149 Object domValue = «propertyName»;
1150 _childNodes.add(domValue);
1154 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1155 String propertyName) {
1156 serializeProperty(container, type.toInstance, propertyName)
1159 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1160 String propertyName) '''
1161 «type.resolvedName» «propertyName» = value.«propertyName»();
1162 if(«propertyName» != null) {
1163 Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
1164 _childNodes.add(domValue);
1168 private def codecClassName(GeneratedType typeSpec) {
1169 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1172 private def codecClassName(Class<?> typeSpec) {
1173 return '''«typeSpec.name»$Broker$Codec$DOM'''
1176 private def HashMap<String, Type> getAllProperties(GeneratedType type) {
1177 val ret = new HashMap<String, Type>();
1178 type.collectAllProperties(ret);
1182 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1183 for (definition : type.methodDefinitions) {
1184 set.put(definition.name, definition.returnType);
1186 for (property : type.properties) {
1187 set.put(property.getterName, property.returnType);
1189 for (parent : type.implements) {
1190 parent.collectAllProperties(set);
1194 def String getGetterName(GeneratedProperty property) {
1195 return "get" + property.name.toFirstUpper
1198 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1199 // NOOP for generic type.
1202 def String getResolvedName(Type type) {
1203 return type.asCtClass.name;
1206 def String getResolvedName(Class<?> type) {
1207 return type.asCtClass.name;
1210 def CtClass asCtClass(Type type) {
1211 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1212 return cls.asCtClass;
1215 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1216 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1220 private def dispatch processException(Class<?> inputType, Exception e) {
1221 log.error("Cannot compile DOM Codec for {}", inputType, e);
1222 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1229 class PropertyPair {
1238 SchemaNode schemaNode;