package org.opendaylight.controller.sal.binding.dom.serializer.impl import javassist.ClassPool import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType import org.opendaylight.yangtools.yang.model.api.SchemaNode import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils import javassist.CtClass import java.util.Map import org.opendaylight.yangtools.yang.common.QName import javassist.CtField import static javassist.Modifier.* import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode import org.opendaylight.yangtools.yang.model.api.ListSchemaNode import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature import org.opendaylight.yangtools.yang.model.api.DataNodeContainer import org.opendaylight.yangtools.sal.binding.model.api.Type import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder import org.opendaylight.yangtools.binding.generator.util.Types import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType import java.util.HashMap import org.opendaylight.yangtools.yang.model.api.DataSchemaNode import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode import java.util.WeakHashMap import java.util.List import java.util.TreeSet import com.google.common.base.Joiner import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject import org.opendaylight.yangtools.sal.binding.model.api.Enumeration import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*; import org.opendaylight.yangtools.yang.binding.BindingDeserializer import org.opendaylight.yangtools.yang.binding.BindingSerializer import org.opendaylight.yangtools.yang.binding.BindingCodec import org.slf4j.LoggerFactory import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException import org.opendaylight.yangtools.yang.model.api.ChoiceNode import java.security.ProtectionDomain import java.io.File class TransformerGenerator { private static val log = LoggerFactory.getLogger(TransformerGenerator) public static val STRING = Types.typeForClass(String); public static val BOOLEAN = Types.typeForClass(Boolean); public static val INTEGER = Types.typeForClass(Integer); //public static val DECIMAL = Types.typeForClass(Decimal); public static val LONG = Types.typeForClass(Long); val ClassPool classPool val extension JavassistUtils utils; CtClass ctTransformator CtClass ctQName @Property var File classFileCapturePath; @Property var Map typeDefinitions; @Property var Map typeToDefinition @Property var Map typeToSchemaNode val Map, Class> generatedClasses = new WeakHashMap(); public new(ClassPool pool) { classPool = pool; utils = new JavassistUtils(pool) ctTransformator = BindingCodec.asCtClass; ctQName = QName.asCtClass } def Class, Object>> transformerFor(Class inputType) { return withClassLoader(inputType.classLoader) [ | val ret = generatedClasses.get(inputType); if (ret !== null) { return ret as Class, Object>>; } val ref = Types.typeForClass(inputType) val node = typeToSchemaNode.get(ref) val typeSpecBuilder = typeToDefinition.get(ref) val typeSpec = typeSpecBuilder.toInstance(); val newret = generateTransformerFor(inputType, typeSpec, node) generatedClasses.put(inputType, newret); return newret as Class, Object>>; ] } private def Class keyTransformerFor(Class inputType, GeneratedType type, ListSchemaNode schema) { return withClassLoader(inputType.classLoader) [ | val transformer = generatedClasses.get(inputType); if (transformer != null) { return transformer; } val newret = generateKeyTransformerFor(inputType, type, schema); generatedClasses.put(inputType, newret); return newret as Class, Object>>; ] } def Class keyTransformer(GeneratedType type, ListSchemaNode node) { val cls = loadClassWithTCCL(type.resolvedName + "Key"); keyTransformerFor(cls, type, node); } private def serializer(Type type) { val cls = loadClassWithTCCL(type.resolvedName); transformerFor(cls); } private def Class getValueSerializer(GeneratedTransferObject type) { val cls = loadClassWithTCCL(type.resolvedName); val transformer = generatedClasses.get(cls); if (transformer !== null) { return transformer; } val valueTransformer = generateValueTransformer(cls, type); generatedClasses.put(cls, valueTransformer); return valueTransformer; } private def generateKeyTransformerFor(Class inputType, GeneratedType typeSpec, ListSchemaNode node) { try { log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader) val properties = typeSpec.allProperties; val ctCls = createClass(inputType.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); staticQNameField(node.QName); implementsType(ctTransformator) method(Object, "toDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' { return null; } ''' ] method(Object, "fromDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' { if($2 == null){ return null; } «QName.name» _localQName = $1; java.util.Map _compositeNode = (java.util.Map) $2; «FOR key : node.keyDefinition» «val propertyName = key.getterName» «val keyDef = node.getDataChildByName(key)» «val property = properties.get(propertyName)» «deserializeProperty(keyDef, property.returnType, property)»; «ENDFOR» «inputType.name» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»); return _value; } ''' ] method(Object, "serialize", Object) [ body = ''' return toDomStatic(QNAME,$1); ''' ] method(Object, "deserialize", Object) [ body = ''' return fromDomStatic(QNAME,$1); ''' ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) log.info("DOM Codec for {} was generated {}",inputType,ret) return ret as Class, ?>>; } catch (Exception e) { processException(inputType,e); return null; } } private def dispatch Class, Object>> generateTransformerFor(Class inputType, GeneratedType typeSpec, SchemaNode node) { try { log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader) val ctCls = createClass(typeSpec.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); staticQNameField(inputType); implementsType(ctTransformator) method(Object, "toDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = serializeBodyFacade(typeSpec, node) ] method(Object, "serialize", Object) [ body = ''' return toDomStatic(QNAME,$1); ''' ] method(Object, "fromDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = deserializeBody(typeSpec, node) ] method(Object, "deserialize", Object) [ body = ''' return fromDomStatic(QNAME,$1); ''' ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) return ret as Class, Object>>; } catch (Exception e) { processException(inputType,e); return null; } } private def dispatch Class, Object>> generateTransformerFor(Class inputType, GeneratedType typeSpec, ChoiceNode node) { try { log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader) val ctCls = createClass(typeSpec.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); //staticQNameField(inputType); implementsType(ctTransformator) method(Object, "toDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' return null; ''' ] method(Object, "serialize", Object) [ body = ''' return null; ''' ] method(Object, "fromDomStatic", QName, Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' return null; ''' ] method(Object, "deserialize", Object) [ body = ''' return null; ''' ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) return ret as Class, Object>>; } catch (Exception e) { processException(inputType,e); return null; } } private def keyConstructorList(List qnames) { val names = new TreeSet() for (name : qnames) { val fieldName = name.getterName; names.add(fieldName); } return Joiner.on(",").join(names); } private def serializeBodyFacade(GeneratedType type, SchemaNode node) { val ret = serializeBody(type, node); return ret; } private def String deserializeBody(GeneratedType type, SchemaNode node) { val ret = deserializeBodyImpl(type, node); return ret; } private def deserializeKey(GeneratedType type, ListSchemaNode node) { if (node.keyDefinition != null && !node.keyDefinition.empty) { return ''' «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode); _builder.setKey(getKey); '''; } } private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) ''' { «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName()); if($2 == null) { return null; } java.util.Map _compositeNode = (java.util.Map) $2; «type.builderName» _builder = new «type.builderName»(); return _builder.build(); } ''' private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode node) ''' { «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName()); if($2 == null) { return null; } java.util.Map _compositeNode = (java.util.Map) $2; «type.builderName» _builder = new «type.builderName»(); «deserializeKey(type, node)» «deserializeDataNodeContainerBody(type, node)» return _builder.build(); } ''' private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) ''' { «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName()); if($2 == null) { return null; } java.util.Map _compositeNode = (java.util.Map) $2; «type.builderName» _builder = new «type.builderName»(); «deserializeDataNodeContainerBody(type, node)» return _builder.build(); } ''' private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) ''' { «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName()); if($2 == null) { return null; } java.util.Map _compositeNode = (java.util.Map) $2; «type.builderName» _builder = new «type.builderName»(); «deserializeDataNodeContainerBody(type, node)» return _builder.build(); } ''' private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) { deserializeNodeContainerBodyImpl(type, type.allProperties, node); } private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap properties, DataNodeContainer node) { val ret = ''' «FOR child : node.childNodes.filter[!augmenting]» «val signature = properties.getFor(child)» «deserializeProperty(child, signature.returnType, signature)» _builder.«signature.name.toSetter»(«signature.name»); «ENDFOR» ''' return ret; } private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type, MethodSignature property) ''' java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName. localName»")); //System.out.println("«property.name»#deCode"+_dom_«property.name»); java.util.List «property.name» = new java.util.ArrayList(); if(_dom_«property.name» != null) { java.util.List _serialized = new java.util.ArrayList(); java.util.Iterator _iterator = _dom_«property.name».iterator(); boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); //System.out.println(" item" + _listItem); Object _value = «type.actualTypeArguments.get(0).serializer.name».fromDomStatic(_localQName,_listItem); //System.out.println(" value" + _value); «property.name».add(_value); _hasNext = _iterator.hasNext(); } } //System.out.println(" list" + «property.name»); ''' private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type, MethodSignature property) ''' java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName. localName»")); java.util.List «property.name» = new java.util.ArrayList(); if(_dom_«property.name» != null) { java.util.List _serialized = new java.util.ArrayList(); java.util.Iterator _iterator = _dom_«property.name».iterator(); boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); if(_listItem instanceof java.util.Map.Entry) { Object _innerValue = ((java.util.Map.Entry) _listItem).getValue(); Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»; «property.name».add(_value); } _hasNext = _iterator.hasNext(); } } ''' private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) ''' java.util.List _dom_«property.name»_list = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»")); «type.resolvedName» «property.name» = null; if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) { java.util.Map.Entry _dom_«property.name» = (java.util.Map.Entry) _dom_«property.name»_list.get(0); Object _inner_value = _dom_«property.name».getValue(); «property.name» = «deserializeValue(type, "_inner_value")»; } ''' private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type, MethodSignature property) ''' java.util.List _dom_«property.name»_list = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»")); «type.resolvedName» «property.name» = null; if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) { java.util.Map _dom_«property.name» = (java.util.Map) _dom_«property.name»_list.get(0); «type.resolvedName» «property.name» = «type.serializer.name».fromDomStatic(_localQName,_dom_«property.name»); } ''' private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) ''' («type.resolvedName») «type.valueSerializer.name».fromDomValue(«domParameter»); ''' private def dispatch Class, Object>> generateValueTransformer( Class inputType, GeneratedTransferObject typeSpec) { try { val returnType = typeSpec.valueReturnType; if (returnType == null) { val ctCls = createDummyImplementation(inputType, typeSpec); val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) return ret as Class, Object>>; } val ctCls = createClass(typeSpec.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); implementsType(ctTransformator) implementsType(BindingDeserializer.asCtClass) method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' { ////System.out.println("«inputType.simpleName»#toDomValue: "+$1); if($1 == null) { return null; } «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1; //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue); «returnType.resolvedName» _value = _encapsulatedValue.getValue(); //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value); return _value; } ''' ] method(Object, "serialize", Object) [ body = ''' { return toDomValue($1); } ''' ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' { //System.out.println("«inputType.simpleName»#fromDomValue: "+$1); if($1 == null) { return null; } «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»; «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue); return _value; } ''' ] method(Object, "deserialize", Object) [ body = '''{ return fromDomValue($1); } ''' ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) log.info("DOM Codec for {} was generated {}",inputType,ret) return ret as Class, Object>>; } catch (Exception e) { log.error("Cannot compile DOM Codec for {}",inputType,e); val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType); exception.addSuppressed(e); throw exception; } } private def createDummyImplementation(Class object, GeneratedTransferObject typeSpec) { log.info("Generating Dummy DOM Codec for {} with {}",object,object.classLoader) return createClass(typeSpec.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); implementsType(ctTransformator) implementsType(BindingDeserializer.asCtClass) method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = '''return null;''' ] method(Object, "serialize", Object) [ body = ''' { return toDomValue($1); } ''' ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = '''return null;''' ] method(Object, "deserialize", Object) [ body = '''{ return fromDomValue($1); } ''' ] ] } private def Type getValueReturnType(GeneratedTransferObject object) { for (prop : object.properties) { if (prop.name == "value") { return prop.returnType; } } if (object.superType != null) { return getValueReturnType(object.superType); } return null; } private def dispatch Class, Object>> generateValueTransformer( Class inputType, Enumeration typeSpec) { try { log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader) val ctCls = createClass(typeSpec.transformatorFqn) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); implementsType(ctTransformator) method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' if($1 == null) { return null; } «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1; return _value.getValue(); ''' ] method(Object, "serialize", Object) [ body = ''' return toDomValue($1); ''' ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC body = ''' if($1 == null) { return null; } _simpleValue = null; «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(null); return _value; ''' ] method(Object, "deserialize", Object) [ body = ''' return fromDomValue($1); ''' ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) log.info("DOM Codec for {} was generated {}",inputType,ret) return ret as Class, Object>>; } catch (CodeGenerationException e) { throw new CodeGenerationException("Cannot compile Transformator for " + inputType,e); } catch (Exception e) { log.error("Cannot compile DOM Codec for {}",inputType,e); val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType); exception.addSuppressed(e); throw exception; } } def Class toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) { val cls = newClass.toClass(loader,domain); if(classFileCapturePath !== null) { newClass.writeFile(classFileCapturePath.absolutePath); } return cls; } def debugWriteClass(CtClass class1) { val path = class1.name.replace(".","/")+".class" val captureFile = new File(classFileCapturePath,path); captureFile.createNewFile } private def dispatch String deserializeValue(Type type, String domParameter) '''(«type.resolvedName») «domParameter»''' /** * Default catch all * **/ private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, MethodSignature property) ''' «type.resolvedName» «property.name» = null; ''' private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type, MethodSignature property) { _deserializeProperty(container, type.toInstance, property) } public static def toSetter(String it) { if (startsWith("is")) { return "set" + substring(2); } else if (startsWith("get")) { return "set" + substring(3); } return "set" + it; } /* private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { Object domValue = «type.serializer».toDomStatic(QNAME,«property.name»); childNodes.add(domValue); } ''' */ private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder''' private def staticQNameField(CtClass it, Class node) { val field = new CtField(ctQName, "QNAME", it); field.modifiers = PUBLIC + FINAL + STATIC; addField(field, '''«node.name».QNAME''') } private def staticQNameField(CtClass it, QName node) { val field = new CtField(ctQName, "QNAME", it); field.modifiers = PUBLIC + FINAL + STATIC; addField(field, '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''') } private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) ''' { «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; «transformDataContainerBody(type.allProperties, node)» return ($r) java.util.Collections.singletonMap(resultName,childNodes); } ''' private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) ''' { «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; «transformDataContainerBody(type.allProperties, node)» return ($r) java.util.Collections.singletonMap(resultName,childNodes); } ''' private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) ''' { «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; «transformDataContainerBody(type.allProperties, node)» return ($r) java.util.Collections.singletonMap(resultName,childNodes); } ''' private def dispatch String serializeBody(GeneratedType type, SchemaNode node) ''' { «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; return ($r) java.util.Collections.singletonMap(resultName,childNodes); } ''' private def transformDataContainerBody(Map properties, DataNodeContainer node) { val ret = ''' «FOR child : node.childNodes.filter[!augmenting]» «var signature = properties.getFor(child)» «serializeProperty(child, signature.returnType, signature)» «ENDFOR» ''' return ret; } def MethodSignature getFor(Map map, DataSchemaNode node) { val sig = map.get(node.getterName); if(sig == null) { return map.get(node.booleanGetterName); } return sig; } private static def String getBooleanGetterName(DataSchemaNode node) { return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName); } private static def String getGetterName(DataSchemaNode node) { return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName); } private static def String getGetterName(QName node) { return "get" + BindingGeneratorUtil.parseToClassName(node.localName); } private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { java.util.Iterator _iterator = «property.name».iterator(); boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); Object _domValue = «type.actualTypeArguments.get(0).serializer.name».toDomStatic(QNAME,_listItem); childNodes.add(_domValue); _hasNext = _iterator.hasNext(); } } ''' private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»"); Object _propValue = «serializeValue(type, property.name)»; if(_propValue != null) { Object _domValue = java.util.Collections.singletonMap(_qname,_propValue); childNodes.add(_domValue); } } ''' private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.name».toDomValue(«parameter»)''' private def dispatch serializeValue(Type signature, String property) '''«property»''' private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, Type type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»"); java.util.Iterator _iterator = «property.name».iterator(); boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); Object _propValue = «property.name»; Object _domValue = java.util.Collections.singletonMap(_qname,_propValue); childNodes.add(_domValue); _hasNext = _iterator.hasNext(); } } ''' /** * Default catch all * **/ private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { Object domValue = «property.name»; childNodes.add(domValue); } ''' private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type, MethodSignature property) { serializeProperty(container, type.toInstance, property) } private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type, MethodSignature property) ''' «property.returnType.resolvedName» «property.name» = value.«property.name»(); if(«property.name» != null) { Object domValue = «type.serializer.name».toDomStatic(QNAME,«property.name»); childNodes.add(domValue); } ''' private def transformatorFqn(GeneratedType typeSpec) { return '''«typeSpec.resolvedName»$Broker$Codec$DOM''' } private def transformatorFqn(Class typeSpec) { return '''«typeSpec.name»$Broker$Codec$DOM''' } private def HashMap getAllProperties(GeneratedType type) { val ret = new HashMap(); type.collectAllProperties(ret); return ret; } private def dispatch void collectAllProperties(GeneratedType type, Map set) { for (definition : type.methodDefinitions) { set.put(definition.name, definition); } for (parent : type.implements) { parent.collectAllProperties(set); } } private def dispatch void collectAllProperties(Type type, Map set) { // NOOP for generic type. } def String getResolvedName(Type type) { return type.asCtClass.name; } def CtClass asCtClass(Type type) { val name = type.fullyQualifiedName val cls = loadClassWithTCCL(type.fullyQualifiedName) return cls.asCtClass; } private def dispatch processException(Class inputType,CodeGenerationException e){ log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.",inputType); throw e; } private def dispatch processException(Class inputType,Exception e){ log.error("Cannot compile DOM Codec for {}",inputType,e); val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType,e); throw exception; } } @Data class PropertyPair { String getterName; Type type; @Property MethodSignature signature; @Property SchemaNode schemaNode; }