summaryrefslogtreecommitdiffstats
path: root/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo
diff options
context:
space:
mode:
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.pojo145
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;
+ }
+}