1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
3 import javassist.ClassPool
4 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
5 import org.opendaylight.yangtools.yang.model.api.SchemaNode
6 import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
7 import javassist.CtClass
9 import org.opendaylight.yangtools.yang.common.QName
10 import javassist.CtField
11 import static javassist.Modifier.*
12 import static org.opendaylight.controller.sal.binding.dom.serializer.impl.CodecMapping.*
13 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
14 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
15 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
16 import org.opendaylight.yangtools.sal.binding.model.api.Type
17 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
18 import org.opendaylight.yangtools.binding.generator.util.Types
19 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
20 import java.util.HashMap
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
22 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
24 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
26 import java.util.TreeSet
27 import com.google.common.base.Joiner
28 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
29 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
30 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
31 import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*;
32 import org.opendaylight.yangtools.yang.binding.BindingDeserializer
33 import org.opendaylight.yangtools.yang.binding.BindingCodec
34 import org.slf4j.LoggerFactory
35 import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
36 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
37 import java.security.ProtectionDomain
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
40 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
41 import java.util.Map.Entry
42 import java.util.AbstractMap.SimpleEntry
43 import org.opendaylight.yangtools.yang.binding.DataObject
44 import org.opendaylight.yangtools.yang.binding.Augmentation
45 import java.util.Iterator
46 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
47 import java.util.concurrent.ConcurrentHashMap
48 import static extension org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils.*;
49 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
50 import org.opendaylight.yangtools.yang.model.util.ExtendedType
51 import org.opendaylight.yangtools.yang.model.util.EnumerationType
52 import static com.google.common.base.Preconditions.*
53 import org.opendaylight.yangtools.yang.model.api.SchemaPath
55 class TransformerGenerator {
57 private static val log = LoggerFactory.getLogger(TransformerGenerator)
59 public static val STRING = Types.typeForClass(String);
60 public static val BOOLEAN = Types.typeForClass(Boolean);
61 public static val INTEGER = Types.typeForClass(Integer);
62 public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
64 //public static val DECIMAL = Types.typeForClass(Decimal);
65 public static val LONG = Types.typeForClass(Long);
67 val ClassPool classPool
68 val extension JavassistUtils utils;
75 var File classFileCapturePath;
78 var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
81 var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
84 var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
87 var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
90 var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
93 var GeneratorListener listener;
95 public static val CLASS_TYPE = Types.typeForClass(Class);
97 public new(ClassPool pool) {
99 utils = new JavassistUtils(pool)
101 BINDING_CODEC = BindingCodec.asCtClass;
102 ctQName = QName.asCtClass
105 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
106 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
107 val ret = getGeneratedClass(inputType)
109 listener.onClassProcessed(inputType);
110 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
112 val ref = Types.typeForClass(inputType)
113 val node = typeToSchemaNode.get(ref)
114 val typeSpecBuilder = typeToDefinition.get(ref)
115 checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
116 val typeSpec = typeSpecBuilder.toInstance();
117 val newret = generateTransformerFor(inputType, typeSpec, node);
118 listener.onClassProcessed(inputType);
119 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
123 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
124 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
125 val ret = getGeneratedClass(inputType)
127 listener.onClassProcessed(inputType);
128 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
130 val ref = Types.typeForClass(inputType)
131 var typeSpecBuilder = typeToDefinition.get(ref)
132 if (typeSpecBuilder == null) {
133 typeSpecBuilder = pathToType.get(node.path);
135 checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
136 val typeSpec = typeSpecBuilder.toInstance();
137 val newret = generateTransformerFor(inputType, typeSpec, node);
138 listener.onClassProcessed(inputType);
139 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
143 def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
144 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
145 val ret = getGeneratedClass(inputType)
147 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
149 val ref = Types.typeForClass(inputType)
150 val node = typeToAugmentation.get(ref)
151 val typeSpecBuilder = typeToDefinition.get(ref)
152 val typeSpec = typeSpecBuilder.toInstance();
153 val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
154 listener.onClassProcessed(inputType);
155 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
159 def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
160 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
161 val ret = getGeneratedClass(inputType)
163 return ret as Class<? extends BindingCodec<Object, Object>>;
165 val ref = Types.typeForClass(inputType)
166 val typeSpecBuilder = typeToDefinition.get(ref)
167 val typeSpec = typeSpecBuilder.toInstance();
168 val newret = generateCaseCodec(inputType, typeSpec, node);
169 return newret as Class<? extends BindingCodec<Object, Object>>;
173 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
174 return withClassLoaderAndLock(parentType.classLoader, lock) [ |
175 val inputName = parentType.name + "Key";
176 val inputType = loadClassWithTCCL(inputName);
177 val ret = getGeneratedClass(inputType)
179 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
181 val ref = Types.typeForClass(parentType)
182 val node = typeToSchemaNode.get(ref) as ListSchemaNode
183 val typeSpecBuilder = typeToDefinition.get(ref)
184 val typeSpec = typeSpecBuilder.identifierDefinition;
185 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
186 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
190 def getIdentifierDefinition(GeneratedTypeBuilder builder) {
191 val inst = builder.toInstance
192 val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
193 return keyMethod.returnType as GeneratedTransferObject
196 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
197 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
198 val ret = getGeneratedClass(inputType)
200 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
202 val ref = Types.typeForClass(inputType)
203 val node = typeToSchemaNode.get(ref) as ListSchemaNode
204 val typeSpecBuilder = typeToDefinition.get(ref)
205 val typeSpec = typeSpecBuilder.toInstance();
206 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
207 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
211 private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
212 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
213 val transformer = getGeneratedClass(inputType)
214 if (transformer != null) {
217 val newret = generateKeyTransformerFor(inputType, type, schema);
218 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
222 private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
225 return loadClassWithTCCL(cls.codecClassName)
226 } catch (ClassNotFoundException e) {
231 private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
232 val cls = loadClassWithTCCL(type.resolvedName + "Key");
233 keyTransformerFor(cls, type, node);
236 private def serializer(Type type, DataSchemaNode node) {
237 val cls = loadClassWithTCCL(type.resolvedName);
238 transformerFor(cls, node);
241 private def Class<?> getValueSerializer(GeneratedTransferObject type) {
242 val cls = loadClassWithTCCL(type.resolvedName);
243 val transformer = cls.generatedClass;
244 if (transformer !== null) {
247 return withClassLoaderAndLock(cls.classLoader, lock) [ |
248 val valueTransformer = generateValueTransformer(cls, type);
249 return valueTransformer;
253 private def Class<?> getValueSerializer(Enumeration type) {
254 val cls = loadClassWithTCCL(type.resolvedName);
255 val transformer = cls.generatedClass;
256 if (transformer !== null) {
260 return withClassLoaderAndLock(cls.classLoader, lock) [ |
261 val valueTransformer = generateValueTransformer(cls, type);
262 return valueTransformer;
266 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
269 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
270 val properties = typeSpec.allProperties;
271 val ctCls = createClass(inputType.codecClassName) [
272 //staticField(Map,"AUGMENTATION_SERIALIZERS");
273 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
274 staticField(it, IDENTITYREF_CODEC, BindingCodec)
275 staticQNameField(node.QName);
276 implementsType(BINDING_CODEC)
277 method(Object, "toDomStatic", QName, Object) [
278 modifiers = PUBLIC + FINAL + STATIC
281 «QName.name» _resultName;
283 _resultName = «QName.name».create($1,QNAME.getLocalName());
287 java.util.List _childNodes = new java.util.ArrayList();
288 «inputType.resolvedName» value = («inputType.name») $2;
289 «FOR key : node.keyDefinition»
290 «val propertyName = key.getterName»
291 «val keyDef = node.getDataChildByName(key)»
292 «val property = properties.get(propertyName)»
293 «serializeProperty(keyDef, property, propertyName)»;
295 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
299 method(Object, "fromDomStatic", QName, Object) [
300 modifiers = PUBLIC + FINAL + STATIC
306 «QName.name» _localQName = $1;
307 java.util.Map _compositeNode = (java.util.Map) $2;
308 boolean _is_empty = true;
309 «FOR key : node.keyDefinition»
310 «val propertyName = key.getterName»
311 «val keyDef = node.getDataChildByName(key)»
312 «val property = properties.get(propertyName)»
313 «deserializeProperty(keyDef, property, propertyName)»;
315 «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
316 keyConstructorList»);
321 method(Object, "serialize", Object) [
324 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
325 «QName.name» _localQName = («QName.name») _input.getKey();
326 «inputType.name» _keyValue = («inputType.name») _input.getValue();
327 return toDomStatic(_localQName,_keyValue);
331 method(Object, "deserialize", Object) [
333 return fromDomStatic(QNAME,$1);
337 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
338 log.info("DOM Codec for {} was generated {}", inputType, ret)
339 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
340 } catch (Exception e) {
341 processException(inputType, e);
346 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
347 ChoiceCaseNode node) {
350 //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
351 val ctCls = createClass(type.codecClassName) [
352 //staticField(Map,"AUGMENTATION_SERIALIZERS");
353 implementsType(BINDING_CODEC)
354 staticQNameField(node.QName);
355 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
356 staticField(it, AUGMENTATION_CODEC, BindingCodec)
357 staticField(it, IDENTITYREF_CODEC, BindingCodec)
358 method(Object, "toDomStatic", QName, Object) [
359 modifiers = PUBLIC + FINAL + STATIC
362 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
363 java.util.List _childNodes = new java.util.ArrayList();
364 «type.resolvedName» value = («type.resolvedName») $2;
365 «transformDataContainerBody(type, type.allProperties, node)»
366 return ($r) _childNodes;
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(type, node)
386 method(Object, "deserialize", Object) [
389 //System.out.println("«type.name»#deserialize: " +$1);
390 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
391 return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue());
397 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Object, Object>>
398 listener?.onDataContainerCodecCreated(inputType, ret);
399 log.info("DOM Codec for {} was generated {}", inputType, ret)
401 } catch (Exception e) {
402 processException(inputType, e);
407 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
408 Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
411 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
412 val ctCls = createClass(typeSpec.codecClassName) [
413 //staticField(Map,"AUGMENTATION_SERIALIZERS");
414 staticQNameField(node.QName);
415 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
416 staticField(it, IDENTITYREF_CODEC, BindingCodec)
417 staticField(it, AUGMENTATION_CODEC, BindingCodec)
418 implementsType(BINDING_CODEC)
419 method(Object, "toDomStatic", QName, Object) [
420 modifiers = PUBLIC + FINAL + STATIC
421 body = serializeBodyFacade(typeSpec, node)
423 method(Object, "serialize", Object) [
426 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
427 «QName.name» _localName = QNAME;
428 if(_input.getKey() != null) {
429 _localName = («QName.name») _input.getKey();
431 return toDomStatic(_localName,_input.getValue());
435 method(Object, "fromDomStatic", QName, Object) [
436 modifiers = PUBLIC + FINAL + STATIC
437 body = deserializeBody(typeSpec, node)
439 method(Object, "deserialize", Object) [
441 return fromDomStatic(QNAME,$1);
446 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
447 listener?.onDataContainerCodecCreated(inputType, ret);
448 log.info("DOM Codec for {} was generated {}", inputType, ret)
450 } catch (Exception e) {
451 processException(inputType, e);
456 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
457 Class<?> inputType, GeneratedType type, AugmentationSchema node) {
460 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
461 val properties = type.allProperties
462 val ctCls = createClass(type.codecClassName) [
463 //staticField(Map,"AUGMENTATION_SERIALIZERS");
464 staticQNameField(node.augmentationQName);
465 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
466 staticField(it, AUGMENTATION_CODEC, BindingCodec)
467 staticField(it, IDENTITYREF_CODEC, BindingCodec)
468 implementsType(BINDING_CODEC)
469 method(Object, "toDomStatic", QName, Object) [
470 modifiers = PUBLIC + FINAL + STATIC
473 //System.out.println("Qname " + $1);
474 //System.out.println("Value " + $2);
475 «QName.name» _resultName = «QName.name».create(QNAME,QNAME.getLocalName());
476 java.util.List _childNodes = new java.util.ArrayList();
477 «type.resolvedName» value = («type.resolvedName») $2;
478 «FOR child : node.childNodes»
479 «var signature = properties.getFor(child)»
480 //System.out.println("«signature.key»" + value.«signature.key»());
481 «serializeProperty(child, signature.value, signature.key)»
483 return ($r) _childNodes;
487 method(Object, "serialize", Object) [
490 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
491 «QName.name» _localName = QNAME;
492 if(_input.getKey() != null) {
493 _localName = («QName.name») _input.getKey();
495 return toDomStatic(_localName,_input.getValue());
499 method(Object, "fromDomStatic", QName, Object) [
500 modifiers = PUBLIC + FINAL + STATIC
503 «QName.name» _localQName = QNAME;
508 java.util.Map _compositeNode = (java.util.Map) $2;
509 //System.out.println(_localQName + " " + _compositeNode);
510 «type.builderName» _builder = new «type.builderName»();
511 boolean _is_empty = true;
512 «FOR child : node.childNodes»
513 «val signature = properties.getFor(child)»
514 «deserializeProperty(child, signature.value, signature.key)»
515 _builder.«signature.key.toSetter»(«signature.key»);
520 return _builder.build();
524 method(Object, "deserialize", Object) [
526 return fromDomStatic(QNAME,$1);
531 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
532 listener?.onDataContainerCodecCreated(inputType, ret);
534 } catch (Exception e) {
535 processException(inputType, e);
540 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
541 Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
544 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
545 val ctCls = createClass(typeSpec.codecClassName) [
546 //staticField(Map,"AUGMENTATION_SERIALIZERS");
547 //staticQNameField(inputType);
548 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
549 staticField(it, IDENTITYREF_CODEC, BindingCodec)
550 staticField(it, CLASS_TO_CASE_MAP, Map)
551 staticField(it, COMPOSITE_TO_CASE, Map)
552 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
553 implementsType(BINDING_CODEC)
554 method(List, "toDomStatic", QName, Object) [
555 modifiers = PUBLIC + FINAL + STATIC
561 «DataObject.name» _baValue = («DataObject.name») $2;
562 Class _baClass = _baValue.getImplementedInterface();
563 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
567 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
568 Object _ret = _codec.serialize(_input);
569 //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
570 return («List.name») _ret;
574 method(Object, "serialize", Object) [
576 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
579 method(Object, "fromDomStatic", QName, Map) [
580 modifiers = PUBLIC + FINAL + STATIC
583 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
585 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
591 method(Object, "deserialize", Object) [
593 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
598 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
599 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
600 listener?.onChoiceCodecCreated(inputType, ret, node);
601 log.info("DOM Codec for {} was generated {}", inputType, ret)
603 } catch (Exception e) {
604 processException(inputType, e);
609 private def keyConstructorList(List<QName> qnames) {
610 val names = new TreeSet<String>()
611 for (name : qnames) {
612 val fieldName = name.getterName;
613 names.add(fieldName);
615 return Joiner.on(",").join(names);
618 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
619 val ret = serializeBody(type, node);
623 private def String deserializeBody(GeneratedType type, SchemaNode node) {
624 val ret = deserializeBodyImpl(type, node);
628 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
629 if (node.keyDefinition != null && !node.keyDefinition.empty) {
631 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
632 _builder.setKey(getKey);
637 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
639 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
644 java.util.Map _compositeNode = (java.util.Map) $2;
645 «type.builderName» _builder = new «type.builderName»();
646 return _builder.build();
650 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
652 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
656 java.util.Map _compositeNode = (java.util.Map) $2;
657 «type.builderName» _builder = new «type.builderName»();
658 «deserializeKey(type, node)»
659 «deserializeDataNodeContainerBody(type, node)»
660 «deserializeAugmentations»
661 return _builder.build();
665 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
667 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
671 java.util.Map _compositeNode = (java.util.Map) $2;
672 «type.builderName» _builder = new «type.builderName»();
673 «deserializeDataNodeContainerBody(type, node)»
674 «deserializeAugmentations»
675 return _builder.build();
679 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
681 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
686 java.util.Map _compositeNode = (java.util.Map) $2;
687 //System.out.println(_localQName + " " + _compositeNode);
688 «type.builderName» _builder = new «type.builderName»();
689 «deserializeDataNodeContainerBody(type, node)»
690 «deserializeAugmentations»
691 return _builder.build();
695 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
696 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
699 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
700 DataNodeContainer node) {
702 boolean _is_empty = true;
703 «FOR child : node.childNodes»
704 «val signature = properties.getFor(child)»
705 «IF signature !== null»
706 «deserializeProperty(child, signature.value, signature.key)»
707 _builder.«signature.key.toSetter»(«signature.key»);
714 def deserializeAugmentations() '''
715 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
716 if(_augmentation != null) {
717 «Iterator.name» _entries = _augmentation.entrySet().iterator();
718 while(_entries.hasNext()) {
719 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
720 //System.out.println("Aug. key:" + _entry.getKey());
721 Class _type = (Class) _entry.getKey();
722 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
724 _builder.addAugmentation(_type,_value);
730 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
731 String propertyName) '''
732 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
734 //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
735 java.util.List «propertyName» = new java.util.ArrayList();
736 if(_dom_«propertyName» != null) {
737 java.util.List _serialized = new java.util.ArrayList();
738 java.util.Iterator _iterator = _dom_«propertyName».iterator();
739 boolean _hasNext = _iterator.hasNext();
741 Object _listItem = _iterator.next();
743 //System.out.println(" item" + _listItem);
744 Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
745 //System.out.println(" value" + _value);
746 «propertyName».add(_value);
747 _hasNext = _iterator.hasNext();
751 //System.out.println(" list" + «propertyName»);
754 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
755 String propertyName) '''
756 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
758 java.util.List «propertyName» = new java.util.ArrayList();
759 if(_dom_«propertyName» != null) {
760 java.util.List _serialized = new java.util.ArrayList();
761 java.util.Iterator _iterator = _dom_«propertyName».iterator();
762 boolean _hasNext = _iterator.hasNext();
765 Object _listItem = _iterator.next();
766 if(_listItem instanceof java.util.Map.Entry) {
767 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
768 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
769 «propertyName».add(_value);
771 _hasNext = _iterator.hasNext();
776 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
777 java.util.List _dom_«propertyName»_list =
778 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
779 «type.resolvedName» «propertyName» = null;
780 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
782 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
783 Object _inner_value = _dom_«propertyName».getValue();
784 «propertyName» = «deserializeValue(type, "_inner_value")»;
788 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
789 String propertyName) '''
790 java.util.List _dom_«propertyName»_list =
791 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
792 «type.resolvedName» «propertyName» = null;
793 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
795 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
796 «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
800 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
801 «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
802 if(«propertyName» != null) {
807 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
808 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
811 private def dispatch String deserializeValue(Enumeration type, String domParameter) '''
812 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
815 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
816 Class<?> inputType, GeneratedTransferObject typeSpec) {
819 val returnType = typeSpec.valueReturnType;
820 if (returnType == null) {
821 val ctCls = createDummyImplementation(inputType, typeSpec);
822 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
823 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
825 var hasBinding = false;
827 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
828 hasBinding = bindingCodecClass !== null;
829 } catch (ClassNotFoundException e) {
832 val hasYangBinding = hasBinding
833 val ctCls = createClass(typeSpec.codecClassName) [
834 //staticField(Map,"AUGMENTATION_SERIALIZERS");
835 if (hasYangBinding) {
836 implementsType(BINDING_CODEC)
837 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
838 staticField(it, IDENTITYREF_CODEC, BindingCodec)
839 implementsType(BindingDeserializer.asCtClass)
841 method(Object, "toDomValue", Object) [
842 modifiers = PUBLIC + FINAL + STATIC
845 //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
850 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
851 //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
852 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
853 //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
854 Object _domValue = «serializeValue(returnType, "_value")»;
859 method(Object, "serialize", Object) [
862 return toDomValue($1);
866 method(Object, "fromDomValue", Object) [
867 modifiers = PUBLIC + FINAL + STATIC
870 //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
875 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
876 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
881 method(Object, "deserialize", Object) [
883 return fromDomValue($1);
889 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
890 log.info("DOM Codec for {} was generated {}", inputType, ret)
891 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
892 } catch (Exception e) {
893 log.error("Cannot compile DOM Codec for {}", inputType, e);
894 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
895 exception.addSuppressed(e);
901 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
902 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
903 return createClass(typeSpec.codecClassName) [
904 //staticField(Map,"AUGMENTATION_SERIALIZERS");
905 implementsType(BINDING_CODEC)
906 implementsType(BindingDeserializer.asCtClass)
907 method(Object, "toDomValue", Object) [
908 modifiers = PUBLIC + FINAL + STATIC
909 body = '''return null;'''
911 method(Object, "serialize", Object) [
914 return toDomValue($1);
918 method(Object, "fromDomValue", Object) [
919 modifiers = PUBLIC + FINAL + STATIC
920 body = '''return null;'''
922 method(Object, "deserialize", Object) [
924 return fromDomValue($1);
931 private def Type getValueReturnType(GeneratedTransferObject object) {
932 for (prop : object.properties) {
933 if (prop.name == "value") {
934 return prop.returnType;
937 if (object.superType != null) {
938 return getValueReturnType(object.superType);
943 private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
945 val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
946 val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
947 val enumSchema = schema.baseType as EnumerationType;
949 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
950 val ctCls = createClass(typeSpec.codecClassName) [
951 //staticField(Map,"AUGMENTATION_SERIALIZERS");
952 //implementsType(BINDING_CODEC)
953 method(Object, "toDomValue", Object) [
954 modifiers = PUBLIC + FINAL + STATIC
959 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
960 «FOR en : enumSchema.values»
961 if(«typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)».equals(_value)) {
969 method(Object, "serialize", Object) [
971 return toDomValue($1);
974 method(Object, "fromDomValue", Object) [
975 modifiers = PUBLIC + FINAL + STATIC
981 String _value = (String) $1;
982 «FOR en : enumSchema.values»
983 if("«en.name»".equals(_value)) {
984 return «typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)»;
991 method(Object, "deserialize", Object) [
993 return fromDomValue($1);
998 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
999 log.info("DOM Codec for {} was generated {}", inputType, ret)
1001 } catch (CodeGenerationException e) {
1002 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1003 } catch (Exception e) {
1004 log.error("Cannot compile DOM Codec for {}", inputType, e);
1005 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
1006 exception.addSuppressed(e);
1012 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
1013 val cls = newClass.toClass(loader, domain);
1014 if (classFileCapturePath !== null) {
1015 newClass.writeFile(classFileCapturePath.absolutePath);
1017 listener?.onCodecCreated(cls);
1021 def debugWriteClass(CtClass class1) {
1022 val path = class1.name.replace(".", "/") + ".class"
1024 val captureFile = new File(classFileCapturePath, path);
1025 captureFile.createNewFile
1029 private def dispatch String deserializeValue(Type type, String domParameter) {
1030 if (INSTANCE_IDENTIFIER.equals(type)) {
1031 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
1032 } else if (CLASS_TYPE.equals(type)) {
1033 return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
1035 return '''(«type.resolvedName») «domParameter»'''
1043 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1044 «type.resolvedName» «propertyName» = null;
1047 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1048 String propertyName) {
1049 _deserializeProperty(container, type.toInstance, propertyName)
1052 public static def toSetter(String it) {
1054 if (startsWith("is")) {
1055 return "set" + substring(2);
1056 } else if (startsWith("get")) {
1057 return "set" + substring(3);
1063 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
1064 «type.resolvedName» «propertyName» = value.«propertyName»();
1065 if(«propertyName» != null) {
1066 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
1067 _childNodes.add(domValue);
1071 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
1073 private def staticQNameField(CtClass it, QName node) {
1074 val field = new CtField(ctQName, "QNAME", it);
1075 field.modifiers = PUBLIC + FINAL + STATIC;
1077 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
1080 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
1082 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1083 java.util.List _childNodes = new java.util.ArrayList();
1084 «type.resolvedName» value = («type.resolvedName») $2;
1085 «transformDataContainerBody(type, type.allProperties, node)»
1086 «serializeAugmentations»
1087 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1091 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
1093 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1094 java.util.List _childNodes = new java.util.ArrayList();
1095 «type.resolvedName» value = («type.resolvedName») $2;
1096 «transformDataContainerBody(type, type.allProperties, node)»
1097 «serializeAugmentations»
1098 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1102 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1104 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1105 java.util.List _childNodes = new java.util.ArrayList();
1106 «type.resolvedName» value = («type.resolvedName») $2;
1107 «transformDataContainerBody(type, type.allProperties, node)»
1108 «serializeAugmentations»
1109 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1113 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1115 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1116 java.util.List _childNodes = new java.util.ArrayList();
1117 «type.resolvedName» value = («type.resolvedName») $2;
1118 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1122 private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
1124 «FOR child : node.childNodes»
1125 «val signature = properties.getFor(child)»
1126 «IF signature !== null»
1127 //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
1128 «serializeProperty(child, signature.value, signature.key)»
1135 private def serializeAugmentations() '''
1136 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1137 if(_augmentations != null) {
1138 _childNodes.addAll(_augmentations);
1142 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1143 var sig = map.get(node.getterName);
1145 return new SimpleEntry(node.getterName, sig);
1147 sig = map.get(node.booleanGetterName);
1149 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1154 private static def String getBooleanGetterName(DataSchemaNode node) {
1155 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1158 private static def String getGetterName(DataSchemaNode node) {
1159 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1162 private static def String getGetterName(QName node) {
1163 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1166 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1167 String propertyName) '''
1168 «type.resolvedName» «propertyName» = value.«propertyName»();
1169 //System.out.println("«propertyName»:" + «propertyName»);
1170 if(«propertyName» != null) {
1171 java.util.Iterator _iterator = «propertyName».iterator();
1172 boolean _hasNext = _iterator.hasNext();
1174 Object _listItem = _iterator.next();
1175 Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
1176 _childNodes.add(_domValue);
1177 _hasNext = _iterator.hasNext();
1182 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1183 «type.resolvedName» «propertyName» = value.«propertyName»();
1185 if(«propertyName» != null) {
1186 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1187 Object _propValue = «serializeValue(type, propertyName)»;
1188 if(_propValue != null) {
1189 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1190 _childNodes.add(_domValue);
1195 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1196 resolvedName».toDomValue(«parameter»)'''
1198 private def dispatch serializeValue(Enumeration type, String parameter) '''«type.valueSerializer.resolvedName».toDomValue(«parameter»)'''
1200 private def dispatch serializeValue(Type signature, String property) {
1201 if (INSTANCE_IDENTIFIER == signature) {
1202 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1203 }else if (CLASS_TYPE.equals(signature)) {
1204 return '''(«QName.resolvedName») «IDENTITYREF_CODEC».serialize(«property»)'''
1206 return '''«property»''';
1209 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1210 String propertyName) '''
1211 «type.resolvedName» «propertyName» = value.«propertyName»();
1212 if(«propertyName» != null) {
1213 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1214 java.util.Iterator _iterator = «propertyName».iterator();
1215 boolean _hasNext = _iterator.hasNext();
1217 Object _listItem = _iterator.next();
1218 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1219 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1220 _childNodes.add(_domValue);
1221 _hasNext = _iterator.hasNext();
1226 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1227 String propertyName) '''
1228 «type.resolvedName» «propertyName» = value.«propertyName»();
1229 if(«propertyName» != null) {
1230 java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1231 _childNodes.addAll(domValue);
1239 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1240 «type.resolvedName» «propertyName» = value.«propertyName»();
1241 if(«propertyName» != null) {
1242 Object domValue = «propertyName»;
1243 _childNodes.add(domValue);
1247 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1248 String propertyName) {
1249 serializeProperty(container, type.toInstance, propertyName)
1252 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1253 String propertyName) '''
1254 «type.resolvedName» «propertyName» = value.«propertyName»();
1255 if(«propertyName» != null) {
1256 Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1257 _childNodes.add(domValue);
1261 private def codecClassName(GeneratedType typeSpec) {
1262 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1265 private def codecClassName(Class<?> typeSpec) {
1266 return '''«typeSpec.name»$Broker$Codec$DOM'''
1269 private def HashMap<String, Type> getAllProperties(GeneratedType type) {
1270 val ret = new HashMap<String, Type>();
1271 type.collectAllProperties(ret);
1275 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1276 for (definition : type.methodDefinitions) {
1277 set.put(definition.name, definition.returnType);
1279 for (property : type.properties) {
1280 set.put(property.getterName, property.returnType);
1282 for (parent : type.implements) {
1283 parent.collectAllProperties(set);
1287 def String getGetterName(GeneratedProperty property) {
1288 return "get" + property.name.toFirstUpper
1291 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1292 // NOOP for generic type.
1295 def String getResolvedName(Type type) {
1296 return type.asCtClass.name;
1299 def String getResolvedName(Class<?> type) {
1300 return type.asCtClass.name;
1303 def CtClass asCtClass(Type type) {
1304 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1305 return cls.asCtClass;
1308 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1309 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1313 private def dispatch processException(Class<?> inputType, Exception e) {
1314 log.error("Cannot compile DOM Codec for {}", inputType, e);
1315 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1322 class PropertyPair {
1331 SchemaNode schemaNode;