diff options
Diffstat (limited to 'dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo')
-rw-r--r-- | dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo new file mode 100644 index 0000000..b3b5cb9 --- /dev/null +++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo @@ -0,0 +1,145 @@ +package org.onap.sdc.dcae.catalog.commons; + +import java.util.List; +import java.util.Map; +import java.util.Collections; + +import java.util.stream.Collectors; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import java.lang.reflect.Type; +import java.lang.reflect.Method; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; + +import java.lang.invoke.MethodHandles; + +import com.google.common.reflect.Invokable; +import com.google.common.reflect.AbstractInvocationHandler; + +import org.apache.commons.beanutils.ConvertUtils; + + +/** + */ +public class Proxy + extends AbstractInvocationHandler { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + + public static @interface DataMap { + + public String map() default ""; + + public boolean proxy() default false; + + public Class elementType() default Void.class; + } + + + public static Constructor<MethodHandles.Lookup> lookupHandleConstructor; + + static { + try { + lookupHandleConstructor = + MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, + int.class); + + if (!lookupHandleConstructor.isAccessible()) { + lookupHandleConstructor.setAccessible(true); + } + } + catch (Exception x) { + throw new RuntimeException(x); + } + } + + + private Map data; + private ProxyBuilder builder; + + protected Proxy(Map theData, ProxyBuilder theBuilder) { + this.data = theData; + this.builder = theBuilder; + } + + public Map data() { + return this.data; + } + + public ProxyBuilder getBuilder() { + return this.builder; + } + + protected Object handleInvocation( + Object theProxy,Method theMethod,Object[] theArgs) + throws Throwable { + if (theMethod.isDefault()) { + final Class<?> declaringClass = theMethod.getDeclaringClass(); + /* + return MethodHandles.lookup() + .in(declaringClass) + .unreflectSpecial(theMethod, declaringClass) + .bindTo(theProxy) + .invokeWithArguments(theArgs); + */ + return lookupHandleConstructor + .newInstance(declaringClass, MethodHandles.Lookup.PRIVATE) + .unreflectSpecial(theMethod, declaringClass) + .bindTo(theProxy) + .invokeWithArguments(theArgs); + } + + String key = theMethod.getName(); + + Proxy.DataMap dataMap = (Proxy.DataMap)theMethod.getAnnotation(Proxy.DataMap.class); + if (dataMap != null) { + String dataKey = dataMap.map(); + if (dataKey != null && !"".equals(dataKey)) + key = dataKey; + } + + //this is ugly, can this be done through an extension mechanism such as plugging in functions? + if ( builder.hasExtension(key) ) + return this.builder.extension(key).apply(this, theArgs); + + Object val = this.data.getOrDefault(key, this.builder.context(key)); + +System.out.println("!! " + key + " : " + val); + +//as we create proxies here we should store them back in the 'data' so that we do not do it again +//can we always 'recognize' them? + if (val instanceof String && + String.class != theMethod.getReturnType()) { + return ConvertUtils.convert((String)val, theMethod.getReturnType()); + } + else if (val instanceof Map) { + if (dataMap != null && dataMap.proxy()) { + return builder.build((Map)val, theMethod.getReturnType()); + } + } + else if (val instanceof List) { + if (dataMap != null && dataMap.proxy()) { + return ((List)val) + .stream() + .map(e -> this.builder.build((Map)e, dataMap.elementType())) + .collect(Collectors.toList()); + } + } +/* + else if (val.getClass().isArray()) { + if (dataMap != null && dataMap.proxy()) { + } + } +*/ + return val; + } +} |