import org.opendaylight.yangtools.yang.model.util.EnumerationType
import static com.google.common.base.Preconditions.*
import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import javassist.CtMethod
+import javassist.CannotCompileException
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.Callable
+import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
class TransformerGenerator {
@Property
var GeneratorListener listener;
+ public static val CLASS_TYPE = Types.typeForClass(Class);
+
public new(ClassPool pool) {
classPool = pool;
utils = new JavassistUtils(pool)
val ctCls = createClass(inputType.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
staticQNameField(node.QName);
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
«QName.name» _resultName;
if($1 != null) {
]
method(Object, "fromDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
if($2 == null){
return null;
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localQName = («QName.name») _input.getKey();
'''
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
return fromDomStatic(QNAME,$1);
'''
]
staticQNameField(node.QName);
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
«QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
java.util.List _childNodes = new java.util.ArrayList();
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localName = QNAME;
]
method(Object, "fromDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = deserializeBody(type, node)
+ bodyChecked = deserializeBody(type, node)
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
{
//System.out.println("«type.name»#deserialize: " +$1);
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
//staticField(Map,"AUGMENTATION_SERIALIZERS");
staticQNameField(node.QName);
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
staticField(it, AUGMENTATION_CODEC, BindingCodec)
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = serializeBodyFacade(typeSpec, node)
+ bodyChecked = serializeBodyFacade(typeSpec, node)
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localName = QNAME;
]
method(Object, "fromDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = deserializeBody(typeSpec, node)
+ bodyChecked = deserializeBody(typeSpec, node)
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
return fromDomStatic(QNAME,$1);
'''
]
staticQNameField(node.augmentationQName);
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
//System.out.println("Qname " + $1);
//System.out.println("Value " + $2);
- «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ «QName.name» _resultName = «QName.name».create(QNAME,QNAME.getLocalName());
java.util.List _childNodes = new java.util.ArrayList();
«type.resolvedName» value = («type.resolvedName») $2;
«FOR child : node.childNodes»
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localName = QNAME;
]
method(Object, "fromDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
«QName.name» _localQName = QNAME;
'''
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
return fromDomStatic(QNAME,$1);
'''
]
//staticField(Map,"AUGMENTATION_SERIALIZERS");
//staticQNameField(inputType);
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
staticField(it, CLASS_TO_CASE_MAP, Map)
staticField(it, COMPOSITE_TO_CASE, Map)
//staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
implementsType(BINDING_CODEC)
method(List, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
if($2 == null) {
return null;
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
'''
]
method(Object, "fromDomStatic", QName, Map) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
«BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
if(_codec != null) {
'''
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
'''
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
- var hasBinding = false;
- try {
- val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
- hasBinding = bindingCodecClass !== null;
- } catch (ClassNotFoundException e) {
- hasBinding = false;
+ if (returnType.name == 'char[]') {
+ val ctCls = createUnionImplementation(inputType, typeSpec);
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
- val hasYangBinding = hasBinding
+
val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- if (hasYangBinding) {
+ if (inputType.isYangBindingAvailable) {
implementsType(BINDING_CODEC)
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
implementsType(BindingDeserializer.asCtClass)
}
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ val ctSpec = typeSpec.asCtClass;
+ bodyChecked = '''
{
//System.out.println("«inputType.simpleName»#toDomValue: "+$1);
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
return toDomValue($1);
}
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
//System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
'''
]
method(Object, "deserialize", Object) [
- body = '''{
+ bodyChecked = '''{
return fromDomValue($1);
}
'''
}
+ def createUnionImplementation(Class<?> inputType, GeneratedTransferObject typeSpec) {
+ return createClass(typeSpec.codecClassName) [
+ val properties = typeSpec.allProperties;
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ if (inputType.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ val ctSpec = inputType.asCtClass;
+ bodyChecked = '''
+ {
+ //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+ «FOR property : properties.entrySet»
+ «IF property.key != "getValue"»
+ «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.key»();
+ if(«property.key» != null) {
+ return «serializeValue(property.value, property.key)»;
+ }
+ «ENDIF»
+ «ENDFOR»
+
+ return null;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ return toDomValue($1);
+ }
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ if($1 instanceof String) {
+ String _simpleValue = (String) $1;
+ return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
+ }
+ return null;
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''{
+ return fromDomValue($1);
+ }
+ '''
+ ]
+ ]
+ }
+
+ def boolean isYangBindingAvailable(Class<?> class1) {
+ try {
+ val bindingCodecClass = class1.classLoader.loadClass(BINDING_CODEC.name);
+ return bindingCodecClass !== null;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
return createClass(typeSpec.codecClassName) [
- //staticField(Map,"AUGMENTATION_SERIALIZERS");
- implementsType(BINDING_CODEC)
- implementsType(BindingDeserializer.asCtClass)
+ if (object.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ //implementsType(BindingDeserializer.asCtClass)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''return null;'''
+ bodyChecked = '''{
+ if($1 == null) {
+ return null;
+ }
+ return $1.toString();
+
+ }'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
{
return toDomValue($1);
}
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''return null;'''
+ bodyChecked = '''return null;'''
]
method(Object, "deserialize", Object) [
- body = '''{
+ bodyChecked = '''{
return fromDomValue($1);
}
'''
//implementsType(BINDING_CODEC)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''{
+ bodyChecked = '''{
if($1 == null) {
return null;
}
'''
]
method(Object, "serialize", Object) [
- body = '''
+ bodyChecked = '''
return toDomValue($1);
'''
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- body = '''
+ bodyChecked = '''
{
if($1 == null) {
return null;
'''
]
method(Object, "deserialize", Object) [
- body = '''
+ bodyChecked = '''
return fromDomValue($1);
'''
]
private def dispatch String deserializeValue(Type type, String domParameter) {
if (INSTANCE_IDENTIFIER.equals(type)) {
-
return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
+ } else if (CLASS_TYPE.equals(type)) {
+ return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
}
-
return '''(«type.resolvedName») «domParameter»'''
}
private def dispatch serializeValue(Type signature, String property) {
if (INSTANCE_IDENTIFIER == signature) {
return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
+ } else if (CLASS_TYPE.equals(signature)) {
+ return '''(«QName.resolvedName») «IDENTITYREF_CODEC».serialize(«property»)'''
+ }
+ if ("char[]" == signature.name) {
+ return '''new String(«property»)''';
}
return '''«property»''';
}
throw exception;
}
+ private def setBodyChecked(CtMethod method, String body) {
+ try {
+ method.setBody(body);
+ } catch (CannotCompileException e) {
+ log.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
+ method.signature, e.message, body)
+ throw e;
+ }
+ }
+
+ private def <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
+ appendClassLoaderIfMissing(cls);
+ ClassLoaderUtils.withClassLoaderAndLock(cls, lock, function);
+ }
+
}
@Data