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 new(ClassPool pool) {
97 utils = new JavassistUtils(pool)
99 BINDING_CODEC = BindingCodec.asCtClass;
100 ctQName = QName.asCtClass
103 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
104 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
105 val ret = getGeneratedClass(inputType)
107 listener.onClassProcessed(inputType);
108 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
110 val ref = Types.typeForClass(inputType)
111 val node = typeToSchemaNode.get(ref)
112 val typeSpecBuilder = typeToDefinition.get(ref)
113 checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
114 val typeSpec = typeSpecBuilder.toInstance();
115 val newret = generateTransformerFor(inputType, typeSpec, node);
116 listener.onClassProcessed(inputType);
117 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
121 def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
122 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
123 val ret = getGeneratedClass(inputType)
125 listener.onClassProcessed(inputType);
126 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
128 val ref = Types.typeForClass(inputType)
129 var typeSpecBuilder = typeToDefinition.get(ref)
130 if (typeSpecBuilder == null) {
131 typeSpecBuilder = pathToType.get(node.path);
133 checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
134 val typeSpec = typeSpecBuilder.toInstance();
135 val newret = generateTransformerFor(inputType, typeSpec, node);
136 listener.onClassProcessed(inputType);
137 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
141 def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
142 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
143 val ret = getGeneratedClass(inputType)
145 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
147 val ref = Types.typeForClass(inputType)
148 val node = typeToAugmentation.get(ref)
149 val typeSpecBuilder = typeToDefinition.get(ref)
150 val typeSpec = typeSpecBuilder.toInstance();
151 val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
152 listener.onClassProcessed(inputType);
153 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
157 def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
158 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
159 val ret = getGeneratedClass(inputType)
161 return ret as Class<? extends BindingCodec<Object, Object>>;
163 val ref = Types.typeForClass(inputType)
164 val typeSpecBuilder = typeToDefinition.get(ref)
165 val typeSpec = typeSpecBuilder.toInstance();
166 val newret = generateCaseCodec(inputType, typeSpec, node);
167 return newret as Class<? extends BindingCodec<Object, Object>>;
171 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
172 return withClassLoaderAndLock(parentType.classLoader, lock) [ |
173 val inputName = parentType.name + "Key";
174 val inputType = loadClassWithTCCL(inputName);
175 val ret = getGeneratedClass(inputType)
177 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
179 val ref = Types.typeForClass(parentType)
180 val node = typeToSchemaNode.get(ref) as ListSchemaNode
181 val typeSpecBuilder = typeToDefinition.get(ref)
182 val typeSpec = typeSpecBuilder.identifierDefinition;
183 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
184 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
188 def getIdentifierDefinition(GeneratedTypeBuilder builder) {
189 val inst = builder.toInstance
190 val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
191 return keyMethod.returnType as GeneratedTransferObject
194 def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
195 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
196 val ret = getGeneratedClass(inputType)
198 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
200 val ref = Types.typeForClass(inputType)
201 val node = typeToSchemaNode.get(ref) as ListSchemaNode
202 val typeSpecBuilder = typeToDefinition.get(ref)
203 val typeSpec = typeSpecBuilder.toInstance();
204 val newret = generateKeyTransformerFor(inputType, typeSpec, node);
205 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
209 private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
210 return withClassLoaderAndLock(inputType.classLoader, lock) [ |
211 val transformer = getGeneratedClass(inputType)
212 if (transformer != null) {
215 val newret = generateKeyTransformerFor(inputType, type, schema);
216 return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
220 private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
223 return loadClassWithTCCL(cls.codecClassName)
224 } catch (ClassNotFoundException e) {
229 private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
230 val cls = loadClassWithTCCL(type.resolvedName + "Key");
231 keyTransformerFor(cls, type, node);
234 private def serializer(Type type, DataSchemaNode node) {
235 val cls = loadClassWithTCCL(type.resolvedName);
236 transformerFor(cls, node);
239 private def Class<?> getValueSerializer(GeneratedTransferObject type) {
240 val cls = loadClassWithTCCL(type.resolvedName);
241 val transformer = cls.generatedClass;
242 if (transformer !== null) {
245 return withClassLoaderAndLock(cls.classLoader, lock) [ |
246 val valueTransformer = generateValueTransformer(cls, type);
247 return valueTransformer;
251 private def Class<?> getValueSerializer(Enumeration type) {
252 val cls = loadClassWithTCCL(type.resolvedName);
253 val transformer = cls.generatedClass;
254 if (transformer !== null) {
258 return withClassLoaderAndLock(cls.classLoader, lock) [ |
259 val valueTransformer = generateValueTransformer(cls, type);
260 return valueTransformer;
264 private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
267 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
268 val properties = typeSpec.allProperties;
269 val ctCls = createClass(inputType.codecClassName) [
270 //staticField(Map,"AUGMENTATION_SERIALIZERS");
271 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
272 staticQNameField(node.QName);
273 implementsType(BINDING_CODEC)
274 method(Object, "toDomStatic", QName, Object) [
275 modifiers = PUBLIC + FINAL + STATIC
278 «QName.name» _resultName;
280 _resultName = «QName.name».create($1,QNAME.getLocalName());
284 java.util.List _childNodes = new java.util.ArrayList();
285 «inputType.resolvedName» value = («inputType.name») $2;
286 «FOR key : node.keyDefinition»
287 «val propertyName = key.getterName»
288 «val keyDef = node.getDataChildByName(key)»
289 «val property = properties.get(propertyName)»
290 «serializeProperty(keyDef, property, propertyName)»;
292 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
296 method(Object, "fromDomStatic", QName, Object) [
297 modifiers = PUBLIC + FINAL + STATIC
303 «QName.name» _localQName = $1;
304 java.util.Map _compositeNode = (java.util.Map) $2;
305 boolean _is_empty = true;
306 «FOR key : node.keyDefinition»
307 «val propertyName = key.getterName»
308 «val keyDef = node.getDataChildByName(key)»
309 «val property = properties.get(propertyName)»
310 «deserializeProperty(keyDef, property, propertyName)»;
312 «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
313 keyConstructorList»);
318 method(Object, "serialize", Object) [
321 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
322 «QName.name» _localQName = («QName.name») _input.getKey();
323 «inputType.name» _keyValue = («inputType.name») _input.getValue();
324 return toDomStatic(_localQName,_keyValue);
328 method(Object, "deserialize", Object) [
330 return fromDomStatic(QNAME,$1);
334 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
335 log.info("DOM Codec for {} was generated {}", inputType, ret)
336 return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
337 } catch (Exception e) {
338 processException(inputType, e);
343 private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
344 ChoiceCaseNode node) {
347 //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
348 val ctCls = createClass(type.codecClassName) [
349 //staticField(Map,"AUGMENTATION_SERIALIZERS");
350 implementsType(BINDING_CODEC)
351 staticQNameField(node.QName);
352 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
353 staticField(it, AUGMENTATION_CODEC, BindingCodec)
354 method(Object, "toDomStatic", QName, Object) [
355 modifiers = PUBLIC + FINAL + STATIC
358 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
359 java.util.List _childNodes = new java.util.ArrayList();
360 «type.resolvedName» value = («type.resolvedName») $2;
361 «transformDataContainerBody(type, type.allProperties, node)»
362 return ($r) _childNodes;
366 method(Object, "serialize", Object) [
369 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
370 «QName.name» _localName = QNAME;
371 if(_input.getKey() != null) {
372 _localName = («QName.name») _input.getKey();
374 return toDomStatic(_localName,_input.getValue());
378 method(Object, "fromDomStatic", QName, Object) [
379 modifiers = PUBLIC + FINAL + STATIC
380 body = deserializeBody(type, node)
382 method(Object, "deserialize", Object) [
385 //System.out.println("«type.name»#deserialize: " +$1);
386 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
387 return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue());
393 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<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 dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
404 Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
407 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
408 val ctCls = createClass(typeSpec.codecClassName) [
409 //staticField(Map,"AUGMENTATION_SERIALIZERS");
410 staticQNameField(node.QName);
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
416 body = serializeBodyFacade(typeSpec, node)
418 method(Object, "serialize", Object) [
421 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
422 «QName.name» _localName = QNAME;
423 if(_input.getKey() != null) {
424 _localName = («QName.name») _input.getKey();
426 return toDomStatic(_localName,_input.getValue());
430 method(Object, "fromDomStatic", QName, Object) [
431 modifiers = PUBLIC + FINAL + STATIC
432 body = deserializeBody(typeSpec, node)
434 method(Object, "deserialize", Object) [
436 return fromDomStatic(QNAME,$1);
441 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
442 listener?.onDataContainerCodecCreated(inputType, ret);
443 log.info("DOM Codec for {} was generated {}", inputType, ret)
445 } catch (Exception e) {
446 processException(inputType, e);
451 private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
452 Class<?> inputType, GeneratedType type, AugmentationSchema node) {
455 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
456 val properties = type.allProperties
457 val ctCls = createClass(type.codecClassName) [
458 //staticField(Map,"AUGMENTATION_SERIALIZERS");
459 staticQNameField(node.augmentationQName);
460 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
461 staticField(it, AUGMENTATION_CODEC, BindingCodec)
462 implementsType(BINDING_CODEC)
463 method(Object, "toDomStatic", QName, Object) [
464 modifiers = PUBLIC + FINAL + STATIC
467 //System.out.println("Qname " + $1);
468 //System.out.println("Value " + $2);
469 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
470 java.util.List _childNodes = new java.util.ArrayList();
471 «type.resolvedName» value = («type.resolvedName») $2;
472 «FOR child : node.childNodes»
473 «var signature = properties.getFor(child)»
474 //System.out.println("«signature.key»" + value.«signature.key»());
475 «serializeProperty(child, signature.value, signature.key)»
477 return ($r) _childNodes;
481 method(Object, "serialize", Object) [
484 java.util.Map.Entry _input = (java.util.Map.Entry) $1;
485 «QName.name» _localName = QNAME;
486 if(_input.getKey() != null) {
487 _localName = («QName.name») _input.getKey();
489 return toDomStatic(_localName,_input.getValue());
493 method(Object, "fromDomStatic", QName, Object) [
494 modifiers = PUBLIC + FINAL + STATIC
497 «QName.name» _localQName = QNAME;
502 java.util.Map _compositeNode = (java.util.Map) $2;
503 //System.out.println(_localQName + " " + _compositeNode);
504 «type.builderName» _builder = new «type.builderName»();
505 boolean _is_empty = true;
506 «FOR child : node.childNodes»
507 «val signature = properties.getFor(child)»
508 «deserializeProperty(child, signature.value, signature.key)»
509 _builder.«signature.key.toSetter»(«signature.key»);
514 return _builder.build();
518 method(Object, "deserialize", Object) [
520 return fromDomStatic(QNAME,$1);
525 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
526 listener?.onDataContainerCodecCreated(inputType, ret);
528 } catch (Exception e) {
529 processException(inputType, e);
534 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
535 Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
538 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
539 val ctCls = createClass(typeSpec.codecClassName) [
540 //staticField(Map,"AUGMENTATION_SERIALIZERS");
541 //staticQNameField(inputType);
542 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
543 staticField(it, CLASS_TO_CASE_MAP, Map)
544 staticField(it, COMPOSITE_TO_CASE, Map)
545 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
546 implementsType(BINDING_CODEC)
547 method(List, "toDomStatic", QName, Object) [
548 modifiers = PUBLIC + FINAL + STATIC
554 «DataObject.name» _baValue = («DataObject.name») $2;
555 Class _baClass = _baValue.getImplementedInterface();
556 «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
560 java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
561 Object _ret = _codec.serialize(_input);
562 //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
563 return («List.name») _ret;
567 method(Object, "serialize", Object) [
569 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
572 method(Object, "fromDomStatic", QName, Map) [
573 modifiers = PUBLIC + FINAL + STATIC
576 «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
578 return _codec.deserialize(new «SimpleEntry.name»($1,$2));
584 method(Object, "deserialize", Object) [
586 throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
591 val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
592 val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
593 listener?.onChoiceCodecCreated(inputType, ret, node);
594 log.info("DOM Codec for {} was generated {}", inputType, ret)
596 } catch (Exception e) {
597 processException(inputType, e);
602 private def keyConstructorList(List<QName> qnames) {
603 val names = new TreeSet<String>()
604 for (name : qnames) {
605 val fieldName = name.getterName;
606 names.add(fieldName);
608 return Joiner.on(",").join(names);
611 private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
612 val ret = serializeBody(type, node);
616 private def String deserializeBody(GeneratedType type, SchemaNode node) {
617 val ret = deserializeBodyImpl(type, node);
621 private def deserializeKey(GeneratedType type, ListSchemaNode node) {
622 if (node.keyDefinition != null && !node.keyDefinition.empty) {
624 «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
625 _builder.setKey(getKey);
630 private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
632 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
637 java.util.Map _compositeNode = (java.util.Map) $2;
638 «type.builderName» _builder = new «type.builderName»();
639 return _builder.build();
643 private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) '''
645 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
649 java.util.Map _compositeNode = (java.util.Map) $2;
650 «type.builderName» _builder = new «type.builderName»();
651 «deserializeKey(type, node)»
652 «deserializeDataNodeContainerBody(type, node)»
653 «deserializeAugmentations»
654 return _builder.build();
658 private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) '''
660 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
664 java.util.Map _compositeNode = (java.util.Map) $2;
665 «type.builderName» _builder = new «type.builderName»();
666 «deserializeDataNodeContainerBody(type, node)»
667 «deserializeAugmentations»
668 return _builder.build();
672 private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
674 «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
679 java.util.Map _compositeNode = (java.util.Map) $2;
680 //System.out.println(_localQName + " " + _compositeNode);
681 «type.builderName» _builder = new «type.builderName»();
682 «deserializeDataNodeContainerBody(type, node)»
683 «deserializeAugmentations»
684 return _builder.build();
688 private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
689 deserializeNodeContainerBodyImpl(type, type.allProperties, node);
692 private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
693 DataNodeContainer node) {
695 boolean _is_empty = true;
696 «FOR child : node.childNodes»
697 «val signature = properties.getFor(child)»
698 «IF signature !== null»
699 «deserializeProperty(child, signature.value, signature.key)»
700 _builder.«signature.key.toSetter»(«signature.key»);
707 def deserializeAugmentations() '''
708 java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
709 if(_augmentation != null) {
710 «Iterator.name» _entries = _augmentation.entrySet().iterator();
711 while(_entries.hasNext()) {
712 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
713 //System.out.println("Aug. key:" + _entry.getKey());
714 Class _type = (Class) _entry.getKey();
715 «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
717 _builder.addAugmentation(_type,_value);
723 private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
724 String propertyName) '''
725 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
727 //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
728 java.util.List «propertyName» = new java.util.ArrayList();
729 if(_dom_«propertyName» != null) {
730 java.util.List _serialized = new java.util.ArrayList();
731 java.util.Iterator _iterator = _dom_«propertyName».iterator();
732 boolean _hasNext = _iterator.hasNext();
734 Object _listItem = _iterator.next();
736 //System.out.println(" item" + _listItem);
737 Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
738 //System.out.println(" value" + _value);
739 «propertyName».add(_value);
740 _hasNext = _iterator.hasNext();
744 //System.out.println(" list" + «propertyName»);
747 private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
748 String propertyName) '''
749 java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
751 java.util.List «propertyName» = new java.util.ArrayList();
752 if(_dom_«propertyName» != null) {
753 java.util.List _serialized = new java.util.ArrayList();
754 java.util.Iterator _iterator = _dom_«propertyName».iterator();
755 boolean _hasNext = _iterator.hasNext();
758 Object _listItem = _iterator.next();
759 if(_listItem instanceof java.util.Map.Entry) {
760 Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
761 Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
762 «propertyName».add(_value);
764 _hasNext = _iterator.hasNext();
769 private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
770 java.util.List _dom_«propertyName»_list =
771 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
772 «type.resolvedName» «propertyName» = null;
773 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
775 java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
776 Object _inner_value = _dom_«propertyName».getValue();
777 «propertyName» = «deserializeValue(type, "_inner_value")»;
781 private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
782 String propertyName) '''
783 java.util.List _dom_«propertyName»_list =
784 _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
785 «type.resolvedName» «propertyName» = null;
786 if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
788 java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
789 «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
793 private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
794 «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
795 if(«propertyName» != null) {
800 private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
801 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
804 private def dispatch String deserializeValue(Enumeration type, String domParameter) '''
805 («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
808 private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
809 Class<?> inputType, GeneratedTransferObject typeSpec) {
812 val returnType = typeSpec.valueReturnType;
813 if (returnType == null) {
814 val ctCls = createDummyImplementation(inputType, typeSpec);
815 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
816 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
818 var hasBinding = false;
820 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
821 hasBinding = bindingCodecClass !== null;
822 } catch (ClassNotFoundException e) {
825 val hasYangBinding = hasBinding
826 val ctCls = createClass(typeSpec.codecClassName) [
827 //staticField(Map,"AUGMENTATION_SERIALIZERS");
828 if (hasYangBinding) {
829 implementsType(BINDING_CODEC)
830 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
831 implementsType(BindingDeserializer.asCtClass)
833 method(Object, "toDomValue", Object) [
834 modifiers = PUBLIC + FINAL + STATIC
837 //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
842 «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
843 //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
844 «returnType.resolvedName» _value = _encapsulatedValue.getValue();
845 //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
846 Object _domValue = «serializeValue(returnType, "_value")»;
851 method(Object, "serialize", Object) [
854 return toDomValue($1);
858 method(Object, "fromDomValue", Object) [
859 modifiers = PUBLIC + FINAL + STATIC
862 //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
867 «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
868 «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
873 method(Object, "deserialize", Object) [
875 return fromDomValue($1);
881 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
882 log.info("DOM Codec for {} was generated {}", inputType, ret)
883 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
884 } catch (Exception e) {
885 log.error("Cannot compile DOM Codec for {}", inputType, e);
886 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
887 exception.addSuppressed(e);
893 private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
894 log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
895 return createClass(typeSpec.codecClassName) [
896 //staticField(Map,"AUGMENTATION_SERIALIZERS");
897 implementsType(BINDING_CODEC)
898 implementsType(BindingDeserializer.asCtClass)
899 method(Object, "toDomValue", Object) [
900 modifiers = PUBLIC + FINAL + STATIC
901 body = '''return null;'''
903 method(Object, "serialize", Object) [
906 return toDomValue($1);
910 method(Object, "fromDomValue", Object) [
911 modifiers = PUBLIC + FINAL + STATIC
912 body = '''return null;'''
914 method(Object, "deserialize", Object) [
916 return fromDomValue($1);
923 private def Type getValueReturnType(GeneratedTransferObject object) {
924 for (prop : object.properties) {
925 if (prop.name == "value") {
926 return prop.returnType;
929 if (object.superType != null) {
930 return getValueReturnType(object.superType);
935 private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
937 val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
938 val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
939 val enumSchema = schema.baseType as EnumerationType;
941 //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
942 val ctCls = createClass(typeSpec.codecClassName) [
943 //staticField(Map,"AUGMENTATION_SERIALIZERS");
944 //implementsType(BINDING_CODEC)
945 method(Object, "toDomValue", Object) [
946 modifiers = PUBLIC + FINAL + STATIC
951 «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
952 «FOR en : enumSchema.values»
953 if(«typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)».equals(_value)) {
961 method(Object, "serialize", Object) [
963 return toDomValue($1);
966 method(Object, "fromDomValue", Object) [
967 modifiers = PUBLIC + FINAL + STATIC
973 String _value = (String) $1;
974 «FOR en : enumSchema.values»
975 if("«en.name»".equals(_value)) {
976 return «typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)»;
983 method(Object, "deserialize", Object) [
985 return fromDomValue($1);
990 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
991 log.info("DOM Codec for {} was generated {}", inputType, ret)
993 } catch (CodeGenerationException e) {
994 throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
995 } catch (Exception e) {
996 log.error("Cannot compile DOM Codec for {}", inputType, e);
997 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
998 exception.addSuppressed(e);
1004 def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
1005 val cls = newClass.toClass(loader, domain);
1006 if (classFileCapturePath !== null) {
1007 newClass.writeFile(classFileCapturePath.absolutePath);
1009 listener?.onCodecCreated(cls);
1013 def debugWriteClass(CtClass class1) {
1014 val path = class1.name.replace(".", "/") + ".class"
1016 val captureFile = new File(classFileCapturePath, path);
1017 captureFile.createNewFile
1021 private def dispatch String deserializeValue(Type type, String domParameter) {
1022 if (INSTANCE_IDENTIFIER.equals(type)) {
1024 return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
1027 return '''(«type.resolvedName») «domParameter»'''
1035 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1036 «type.resolvedName» «propertyName» = null;
1039 private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1040 String propertyName) {
1041 _deserializeProperty(container, type.toInstance, propertyName)
1044 public static def toSetter(String it) {
1046 if (startsWith("is")) {
1047 return "set" + substring(2);
1048 } else if (startsWith("get")) {
1049 return "set" + substring(3);
1055 private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
1056 «type.resolvedName» «propertyName» = value.«propertyName»();
1057 if(«propertyName» != null) {
1058 Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
1059 _childNodes.add(domValue);
1063 private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
1065 private def staticQNameField(CtClass it, QName node) {
1066 val field = new CtField(ctQName, "QNAME", it);
1067 field.modifiers = PUBLIC + FINAL + STATIC;
1069 '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
1072 private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
1074 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1075 java.util.List _childNodes = new java.util.ArrayList();
1076 «type.resolvedName» value = («type.resolvedName») $2;
1077 «transformDataContainerBody(type, type.allProperties, node)»
1078 «serializeAugmentations»
1079 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1083 private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
1085 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1086 java.util.List _childNodes = new java.util.ArrayList();
1087 «type.resolvedName» value = («type.resolvedName») $2;
1088 «transformDataContainerBody(type, type.allProperties, node)»
1089 «serializeAugmentations»
1090 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1094 private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
1096 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1097 java.util.List _childNodes = new java.util.ArrayList();
1098 «type.resolvedName» value = («type.resolvedName») $2;
1099 «transformDataContainerBody(type, type.allProperties, node)»
1100 «serializeAugmentations»
1101 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1105 private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
1107 «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
1108 java.util.List _childNodes = new java.util.ArrayList();
1109 «type.resolvedName» value = («type.resolvedName») $2;
1110 return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
1114 private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
1116 «FOR child : node.childNodes»
1117 «val signature = properties.getFor(child)»
1118 «IF signature !== null»
1119 //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
1120 «serializeProperty(child, signature.value, signature.key)»
1127 private def serializeAugmentations() '''
1128 java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
1129 if(_augmentations != null) {
1130 _childNodes.addAll(_augmentations);
1134 def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
1135 var sig = map.get(node.getterName);
1137 return new SimpleEntry(node.getterName, sig);
1139 sig = map.get(node.booleanGetterName);
1141 return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
1146 private static def String getBooleanGetterName(DataSchemaNode node) {
1147 return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1150 private static def String getGetterName(DataSchemaNode node) {
1151 return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
1154 private static def String getGetterName(QName node) {
1155 return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
1158 private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
1159 String propertyName) '''
1160 «type.resolvedName» «propertyName» = value.«propertyName»();
1161 //System.out.println("«propertyName»:" + «propertyName»);
1162 if(«propertyName» != null) {
1163 java.util.Iterator _iterator = «propertyName».iterator();
1164 boolean _hasNext = _iterator.hasNext();
1166 Object _listItem = _iterator.next();
1167 Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
1168 _childNodes.add(_domValue);
1169 _hasNext = _iterator.hasNext();
1174 private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
1175 «type.resolvedName» «propertyName» = value.«propertyName»();
1177 if(«propertyName» != null) {
1178 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1179 Object _propValue = «serializeValue(type, propertyName)»;
1180 if(_propValue != null) {
1181 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1182 _childNodes.add(_domValue);
1187 private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
1188 resolvedName».toDomValue(«parameter»)'''
1190 private def dispatch serializeValue(Enumeration type, String parameter) '''«type.valueSerializer.resolvedName».toDomValue(«parameter»)'''
1192 private def dispatch serializeValue(Type signature, String property) {
1193 if (INSTANCE_IDENTIFIER == signature) {
1194 return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
1196 return '''«property»''';
1199 private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
1200 String propertyName) '''
1201 «type.resolvedName» «propertyName» = value.«propertyName»();
1202 if(«propertyName» != null) {
1203 «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
1204 java.util.Iterator _iterator = «propertyName».iterator();
1205 boolean _hasNext = _iterator.hasNext();
1207 Object _listItem = _iterator.next();
1208 Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
1209 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
1210 _childNodes.add(_domValue);
1211 _hasNext = _iterator.hasNext();
1216 private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
1217 String propertyName) '''
1218 «type.resolvedName» «propertyName» = value.«propertyName»();
1219 if(«propertyName» != null) {
1220 java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1221 _childNodes.addAll(domValue);
1229 private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
1230 «type.resolvedName» «propertyName» = value.«propertyName»();
1231 if(«propertyName» != null) {
1232 Object domValue = «propertyName»;
1233 _childNodes.add(domValue);
1237 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
1238 String propertyName) {
1239 serializeProperty(container, type.toInstance, propertyName)
1242 private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
1243 String propertyName) '''
1244 «type.resolvedName» «propertyName» = value.«propertyName»();
1245 if(«propertyName» != null) {
1246 Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
1247 _childNodes.add(domValue);
1251 private def codecClassName(GeneratedType typeSpec) {
1252 return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
1255 private def codecClassName(Class<?> typeSpec) {
1256 return '''«typeSpec.name»$Broker$Codec$DOM'''
1259 private def HashMap<String, Type> getAllProperties(GeneratedType type) {
1260 val ret = new HashMap<String, Type>();
1261 type.collectAllProperties(ret);
1265 private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
1266 for (definition : type.methodDefinitions) {
1267 set.put(definition.name, definition.returnType);
1269 for (property : type.properties) {
1270 set.put(property.getterName, property.returnType);
1272 for (parent : type.implements) {
1273 parent.collectAllProperties(set);
1277 def String getGetterName(GeneratedProperty property) {
1278 return "get" + property.name.toFirstUpper
1281 private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
1282 // NOOP for generic type.
1285 def String getResolvedName(Type type) {
1286 return type.asCtClass.name;
1289 def String getResolvedName(Class<?> type) {
1290 return type.asCtClass.name;
1293 def CtClass asCtClass(Type type) {
1294 val cls = loadClassWithTCCL(type.fullyQualifiedName)
1295 return cls.asCtClass;
1298 private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
1299 log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
1303 private def dispatch processException(Class<?> inputType, Exception e) {
1304 log.error("Cannot compile DOM Codec for {}", inputType, e);
1305 val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
1312 class PropertyPair {
1321 SchemaNode schemaNode;