Ver Fonte

adapter: final refactoring before publication

Mariusz Sieroń há 6 anos atrás
pai
commit
892af36071

+ 0 - 29
assira.drafts/src/main/java/net/ranides/assira/reflection/Adapter.java

@@ -1,29 +0,0 @@
-package net.ranides.assira.reflection;
-
-import net.ranides.assira.collection.maps.HashMap;
-import net.ranides.assira.generic.Tuple;
-import net.ranides.assira.reflection.asm.cg.CGAdapter;
-
-import java.util.Map;
-import java.util.function.Function;
-
-public class Adapter {
-
-    private static Map<Tuple, IClass<?>> GENERATED = new HashMap<>();
-
-    public static <T,S> Function<S,T> adapter(IClass<T> target, IClass<S> source) {
-        IClass<?> ac = GENERATED.computeIfAbsent(
-                new Tuple(target, source),
-                $0 -> new CGAdapter(target, source).load(IClassLoader.system()));
-        return a -> target.cast(ac.construct(a));
-    }
-
-    public static <T> T cast(Class<T> type, Object that) {
-        return cast(IClass.typeinfo(type), that);
-    }
-
-    public static <T,S> T cast(IClass<T> type, S that) {
-        return adapter(type, IClass.typefor(that)).apply(that);
-    }
-
-}

+ 50 - 0
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/AdapterFactory.java

@@ -0,0 +1,50 @@
+package net.ranides.assira.reflection.asm;
+
+import net.ranides.assira.collection.maps.HashMap;
+import net.ranides.assira.generic.Tuple;
+import net.ranides.assira.reflection.IClass;
+import net.ranides.assira.reflection.IClassLoader;
+import net.ranides.assira.reflection.asm.impl.CGAdapter;
+
+import java.util.Map;
+import java.util.function.Function;
+
+public class AdapterFactory {
+
+    private final IClassLoader loader;
+
+    private final Map<Tuple, IClass<?>> GENERATED = new HashMap<>();
+
+    private static final class Li {
+
+        public static final AdapterFactory SYSTEM = new AdapterFactory(IClassLoader.system());
+
+    }
+
+    public AdapterFactory(IClassLoader loader) {
+        this.loader = loader;
+    }
+
+    public static AdapterFactory system() {
+        return Li.SYSTEM;
+    }
+
+    public IClassLoader loader() {
+        return loader;
+    }
+
+    public <T,S> Function<S,T> adapter(IClass<T> target, IClass<S> source) {
+        Tuple key = new Tuple(target, source);
+        IClass<?> ac = GENERATED.computeIfAbsent(key, $0 -> CGAdapter.load(this, target, source));
+        return a -> target.cast(ac.construct(a));
+    }
+
+    public <T> T cast(Class<T> type, Object that) {
+        return cast(IClass.typeinfo(type), that);
+    }
+
+    public <T,S> T cast(IClass<T> type, S that) {
+        return adapter(type, IClass.typefor(that)).apply(that);
+    }
+
+}

+ 2 - 2
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/cg/Adapt.java

@@ -1,4 +1,4 @@
-package net.ranides.assira.reflection.asm.cg;
+package net.ranides.assira.reflection.asm;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
@@ -8,5 +8,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 @Retention(RUNTIME)
 @Target({TYPE})
-public @interface Adapt {
+public @interface AdapterWrapper {
 }

+ 33 - 27
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/cg/CGAdapter.java

@@ -1,12 +1,9 @@
-package net.ranides.assira.reflection.asm.cg;
+package net.ranides.assira.reflection.asm.impl;
 
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import net.ranides.assira.reflection.*;
-import net.ranides.assira.reflection.IClassLoader;
-import net.ranides.assira.reflection.asm.AsmClassBuilder;
-import net.ranides.assira.reflection.asm.AsmMethodBuilder;
-import net.ranides.assira.reflection.asm.AsmSupport;
+import net.ranides.assira.reflection.asm.*;
 
 import java.util.*;
 import java.util.function.Function;
@@ -28,6 +25,8 @@ public class CGAdapter {
 
     private static final IMethod M_THAT = IClass.typeinfo(CGAdapterWrapper.class).method("net_ranides_assira_cg_that").get();
 
+    private final AdapterFactory factory;
+
     private final IClass<?> adapter;
 
     private final IClass<?> that;
@@ -38,13 +37,18 @@ public class CGAdapter {
 
     private final AsmClassBuilder writer;
 
-    private final byte[] bytecode;
-
     private final List<IMethod> reflective;
 
     private final List<AdapterMeta> adapters;
 
-    public CGAdapter(IClass<?> adapter, IClass<?> that) {
+    private final IClass<?> generated;
+
+    public static IClass<?> load(AdapterFactory factory, IClass<?> adapter, IClass<?> that) {
+        return new CGAdapter(factory, adapter, that).generated;
+    }
+
+    private CGAdapter(AdapterFactory factory, IClass<?> adapter, IClass<?> that) {
+        this.factory = factory;
         this.adapter = adapter;
         this.that = that;
         this.name = that.name() + "$asm:" + AsmSupport.escape(adapter.name());
@@ -60,42 +64,44 @@ public class CGAdapter {
 
         writer.field(IAttributes.of(IAttribute.PRIVATE), that, F_THAT);
 
-        putConstructor();
+        implementConstructor();
 
-        putToString();
+        implementInterface();
 
-        putWrapperThat();
+        implementToString();
 
         for(IMethod m : adapter.methods()) {
             new MethodLink(m).link();
         }
 
+        declareStatic();
+
+        this.generated = factory.loader().defineClass(name, writer.bytecode());
+
+        initStatic();
+    }
+
+    private void declareStatic() {
         for(int i=0, n=reflective.size(); i<n; i++) {
             writer.field(A_METHODS, IClass.typeinfo(IMethod.class), F_METHODS+i);
         }
         for(int i=0, n=adapters.size(); i<n; i++) {
             writer.field(A_ADAPTERS, IClass.typeinfo(Function.class), F_ADAPTERS + i);
         }
-        this.bytecode = writer.bytecode();
     }
 
-    private void init(IClass<?> ic) {
+    private void initStatic() {
         for(int i=0, n=reflective.size(); i<n; i++) {
-            ic.field(F_METHODS+i).get().set(null, reflective.get(i));
+            generated.field(F_METHODS+i).get().set(null, reflective.get(i));
         }
+
         for(int i=0, n=adapters.size(); i<n; i++) {
             AdapterMeta meta = adapters.get(i);
-            ic.field(F_ADAPTERS+i).get().set(null, Adapter.adapter(meta.target, meta.source));
+            generated.field(F_ADAPTERS+i).get().set(null, this.factory.adapter(meta.target, meta.source));
         }
     }
 
-    public IClass<?> load(IClassLoader loader) {
-        IClass<?> ic = loader.defineClass(name, bytecode);
-        init(ic);
-        return ic;
-    }
-
-    private void putConstructor() {
+    private void implementConstructor() {
         /// Adapter(That that) {
         ///     super();
         ///     this.that = that;
@@ -115,7 +121,7 @@ public class CGAdapter {
         m.end();
     }
 
-    private void putToString() {
+    private void implementToString() {
         /// String toString() {
         ///     String v = that.toString();
         ///     return new StringBuilder(24 + v.length()).append("Adapter{").append(that).append("=> some type}").toString()
@@ -153,7 +159,7 @@ public class CGAdapter {
         m.end();
     }
 
-    private void putWrapperThat() {
+    private void implementInterface() {
         /// public Object net_ranides_assira_cg_that() {
         ///     return this.that;
         /// }
@@ -194,7 +200,7 @@ public class CGAdapter {
         }
 
         private int initResultAdapter() {
-            if(!method.returns().annotation(Adapt.class).isPresent()) {
+            if(!method.returns().annotation(AdapterWrapper.class).isPresent()) {
                 return -1;
             }
             AdapterMeta meta = new AdapterMeta(target.returns(), method.returns());
@@ -253,7 +259,7 @@ public class CGAdapter {
                 m.dup();
                 m.push(i);
                 m.load(iargs.get(i), i + 1);
-                if(iargs.get(i).annotation(Adapt.class).isPresent()) {
+                if(iargs.get(i).annotation(AdapterWrapper.class).isPresent()) {
                     m.invokeVirtual(M_THAT);
                 }
                 if (iargs.get(i).attribute(IAttribute.PRIMITIVE)) {
@@ -267,7 +273,7 @@ public class CGAdapter {
         private void invokeDirect() {
             for(int i=0, n=iargs.size(); i<n; i++) {
                 m.load(iargs.get(i), i+1);
-                if(iargs.get(i).annotation(Adapt.class).isPresent()) {
+                if(iargs.get(i).annotation(AdapterWrapper.class).isPresent()) {
                     m.invokeVirtual(M_THAT);
                 }
                 if(!iargs.get(i).isSubclass(oargs.get(i))) {

+ 1 - 1
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/cg/CGAdapterReflect.java

@@ -1,4 +1,4 @@
-package net.ranides.assira.reflection.asm.cg;
+package net.ranides.assira.reflection.asm.impl;
 
 import net.ranides.assira.collection.maps.HashMap;
 import net.ranides.assira.collection.query.CQuery;

+ 1 - 1
assira.drafts/src/main/java/net/ranides/assira/reflection/asm/cg/CGAdapterWrapper.java

@@ -1,4 +1,4 @@
-package net.ranides.assira.reflection.asm.cg;
+package net.ranides.assira.reflection.asm.impl;
 
 public interface CGAdapterWrapper {
 

+ 1 - 1
assira.drafts/src/test/java/net/ranides/assira/example/IRecord4Proxy.java

@@ -4,7 +4,7 @@ import net.ranides.assira.reflection.IClass;
 import net.ranides.assira.reflection.IMethod;
 import net.ranides.assira.reflection.adapter.example.AbstractRecord;
 import net.ranides.assira.reflection.adapter.example.InnerDefs;
-import net.ranides.assira.reflection.asm.cg.CGAdapterWrapper;
+import net.ranides.assira.reflection.asm.impl.CGAdapterWrapper;
 
 import java.util.List;
 import java.util.Map;

+ 2 - 6
assira.drafts/src/test/java/net/ranides/assira/example/IRecord4ProxyDump.java

@@ -1,17 +1,13 @@
 package net.ranides.assira.example;
 
 import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.ConstantDynamic;
 import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Handle;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
-import org.objectweb.asm.TypePath;
+
 public class IRecord4ProxyDump implements Opcodes {
 
     public static byte[] dump () throws Exception {
@@ -21,7 +17,7 @@ public class IRecord4ProxyDump implements Opcodes {
         MethodVisitor methodVisitor;
         AnnotationVisitor annotationVisitor0;
 
-        classWriter.visit(V1_8, ACC_PUBLIC | ACC_SUPER, "net/ranides/assira/example/IRecord4Proxy", null, "java/lang/Object", new String[] { "net/ranides/assira/reflection/adapter/example/InnerDefs$IRecord3", "net/ranides/assira/reflection/asm/cg/CGAdapterWrapper" });
+        classWriter.visit(V1_8, ACC_PUBLIC | ACC_SUPER, "net/ranides/assira/example/IRecord4Proxy", null, "java/lang/Object", new String[] { "net/ranides/assira/reflection/adapter/example/InnerDefs$IRecord3", "net/ranides/assira/reflection/asm/CGAdapterWrapper"});
 
         classWriter.visitSource("IRecord4Proxy.java", null);
 

+ 11 - 10
assira.drafts/src/test/java/net/ranides/assira/reflection/AdapterTest.java

@@ -12,6 +12,7 @@ import net.ranides.assira.reflection.adapter.model2.Image2error;
 import net.ranides.assira.reflection.adapter.model2.Screen2;
 import net.ranides.assira.reflection.adapter.model3.Image3;
 import net.ranides.assira.reflection.adapter.model3.Screen3;
+import net.ranides.assira.reflection.asm.AdapterFactory;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.objectweb.asm.util.ASMifier;
@@ -27,9 +28,9 @@ public class AdapterTest {
     public void castM1P() {
         Screen0 screen0 = new Screen0(640, 480);
 
-        Screen1P screen1 = Adapter.cast(Screen1P.class, screen0);
-        Screen1P screen12 = Adapter.cast(Screen1P.class, screen0);
-        Screen1P screen13 = Adapter.cast(Screen1P.class, screen0);
+        Screen1P screen1 = AdapterFactory.system().cast(Screen1P.class, screen0);
+        Screen1P screen12 = AdapterFactory.system().cast(Screen1P.class, screen0);
+        Screen1P screen13 = AdapterFactory.system().cast(Screen1P.class, screen0);
 
         assertEquals("640x480 false", screen1.width()+"x"+screen1.height()+" "+screen1.isWide());
 
@@ -47,7 +48,7 @@ public class AdapterTest {
     public void castM1() {
         Screen0 screen0 = new Screen0(640, 480);
 
-        Screen1 screen1 = Adapter.cast(Screen1.class, screen0);
+        Screen1 screen1 = AdapterFactory.system().cast(Screen1.class, screen0);
 
         assertEquals("640x480 false", screen1.width()+"x"+screen1.height()+" "+screen1.isWide());
 
@@ -72,7 +73,7 @@ public class AdapterTest {
     public void castM2() {
         Screen0 screen0 = new Screen0(640, 480);
 
-        Screen2 screen2 = Adapter.cast(Screen2.class, screen0);
+        Screen2 screen2 = AdapterFactory.system().cast(Screen2.class, screen0);
 
         assertEquals("640x480 false", screen2.width()+"x"+screen2.height()+" "+screen2.isWide());
 
@@ -95,8 +96,8 @@ public class AdapterTest {
 
     @Test
     public void castM3() {
-        Screen3 buffer = Adapter.cast(Screen3.class, new Screen0(32,32));
-        Screen3 screen = Adapter.cast(Screen3.class, new Screen0(640, 480));
+        Screen3 buffer = AdapterFactory.system().cast(Screen3.class, new Screen0(32,32));
+        Screen3 screen = AdapterFactory.system().cast(Screen3.class, new Screen0(640, 480));
 
         assertEquals("640x480 false", screen.width()+"x"+screen.height()+" "+screen.isWide());
 
@@ -128,7 +129,7 @@ public class AdapterTest {
     public void castExample() {
         InnerDefs.MutableRecord source = new InnerDefs.MutableRecord(7,3);
 
-        InnerDefs.IRecord3 target3 = Adapter.cast(InnerDefs.IRecord3.class, source);
+        InnerDefs.IRecord3 target3 = AdapterFactory.system().cast(InnerDefs.IRecord3.class, source);
 
         assertEquals(7, target3.getX());
         assertEquals(3, target3.getY());
@@ -140,12 +141,12 @@ public class AdapterTest {
         assertEquals(56, source.resize(4).getX());
         assertEquals(1344, target3.area());
 
-        InnerDefs.IRecord1 target1 = Adapter.cast(InnerDefs.IRecord1.class, source);
+        InnerDefs.IRecord1 target1 = AdapterFactory.system().cast(InnerDefs.IRecord1.class, source);
         assertEquals(56, target1.getX());
         assertEquals(24, target1.getY());
         assertEquals(1344, target1.area());
 
-        InnerDefs.IRecord2 target2 = Adapter.cast(InnerDefs.IRecord2.class, source);
+        InnerDefs.IRecord2 target2 = AdapterFactory.system().cast(InnerDefs.IRecord2.class, source);
         assertEquals(56, target2.getX());
         assertEquals(24, target2.getY());
         assertEquals(1344, target2.area());

+ 2 - 2
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model3/Image3.java

@@ -1,8 +1,8 @@
 package net.ranides.assira.reflection.adapter.model3;
 
-import net.ranides.assira.reflection.asm.cg.Adapt;
+import net.ranides.assira.reflection.asm.AdapterWrapper;
 
-@Adapt
+@AdapterWrapper
 public interface Image3 {
 
     String getId();

+ 2 - 2
assira.drafts/src/test/java/net/ranides/assira/reflection/adapter/model3/Screen3.java

@@ -1,8 +1,8 @@
 package net.ranides.assira.reflection.adapter.model3;
 
-import net.ranides.assira.reflection.asm.cg.Adapt;
+import net.ranides.assira.reflection.asm.AdapterWrapper;
 
-@Adapt
+@AdapterWrapper
 public interface Screen3 {
 
     int width();