Ranides Atterwim 5 jaren geleden
bovenliggende
commit
ba83731f84

+ 4 - 4
assira/src/main/java/net/ranides/assira/generic/TypeToken.java

@@ -60,8 +60,6 @@ import net.ranides.assira.reflection.impl.AClass;
  */
 public abstract class TypeToken<T> extends AClass<T> implements Serializable {
 
-    private static final long serialVersionUID = 1L;
-    
     private final IClass<T> type;
 
     /**
@@ -175,7 +173,9 @@ public abstract class TypeToken<T> extends AClass<T> implements Serializable {
     public List<IClass<?>> params() {
         return type.params();
     }
-    
-    
+
+    protected Object writeReplace() {
+        return type;
+    }
 
 }

+ 47 - 5
assira/src/main/java/net/ranides/assira/reflection/impl/RContext.java

@@ -6,15 +6,19 @@
  */
 package net.ranides.assira.reflection.impl;
 
+import lombok.RequiredArgsConstructor;
+
+import net.ranides.assira.collection.lists.RTList;
+import net.ranides.assira.collection.maps.HashMap;
+import net.ranides.assira.generic.SerializationUtils;
+import net.ranides.assira.reflection.*;
+
 import java.io.Serializable;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
 import java.util.Map;
-import net.ranides.assira.collection.lists.RTList;
-import net.ranides.assira.collection.maps.HashMap;
-import net.ranides.assira.generic.SerializationUtils;
-import net.ranides.assira.reflection.IContext;
 
 /**
  *
@@ -84,5 +88,43 @@ public final class RContext extends AContext implements Serializable {
         map.putAll(super.map());
         return map;
     }
-    
+
+    protected Object writeReplace() {
+        String[] cKeys = keys.stream().map(TypeVariable::getName).toArray(String[]::new);
+        IClass[] cVars = vars.stream().map(this::typeinfo).toArray(IClass[]::new);
+        return new SContext(parent, new RTList<>(cKeys), new RTList<>(cVars));
+    }
+
+    @RequiredArgsConstructor
+    private static final class SContext extends AContext implements Serializable {
+
+        private final AContext parent;
+        private final RTList<String> keys;
+        private final RTList<IClass<?>> vars;
+
+        @Override
+        protected Type resolve(TypeVariable type) {
+            for(int i=0, n=keys.size(); i<n; i++) {
+                if( match(keys.get(i), type) ) {
+                    return vars.get(i).reflective();
+                }
+            }
+            return parent.resolve(type);
+        }
+
+        private boolean match(String key, TypeVariable type) {
+            return key.equals(type.getName());
+        }
+
+        @Override
+        public Map<String, Type> map() {
+            HashMap<String, Type> map = new HashMap<>();
+            for(int i=0, n=keys.size(); i<n; i++) {
+                map.put(keys.get(i), vars.get(i).reflective());
+            }
+            map.putAll(super.map());
+            return map;
+        }
+
+    }
 }

+ 45 - 2
assira/src/main/java/net/ranides/assira/reflection/impl/RFClass.java

@@ -6,10 +6,14 @@
  */
 package net.ranides.assira.reflection.impl;
 
+import lombok.RequiredArgsConstructor;
+import org.jetbrains.annotations.NotNull;
+
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedType;
 import java.lang.reflect.Type;
+import java.util.Arrays;
 import java.util.List;
 
 import net.ranides.assira.collection.query.CQuery;
@@ -23,8 +27,6 @@ import net.ranides.assira.reflection.*;
  */
 public class RFClass<T> extends AClass<T> implements Serializable {
 
-    private static final long serialVersionUID = 1L;
-
     private final IClass<T> itype;
     private final AnnotatedType atype;
 
@@ -131,4 +133,45 @@ public class RFClass<T> extends AClass<T> implements Serializable {
         return itype;
     }
 
+    protected Object writeReplace() {
+        final IContext cContext = super.context();
+        final IClass<?> ciType = this.itype;
+        final AContainer cAnnotations = new AContainer(atype);
+
+        return SerializationUtils.proxy(() -> FClass.newRFClass(cContext, ciType, cAnnotations));
+    }
+
+    @RequiredArgsConstructor
+    private static class AContainer implements AnnotatedType, Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        private final Annotation[] annotations;
+        private final Annotation[] declared;
+
+        public AContainer(AnnotatedType atype) {
+            this.annotations = atype.getAnnotations();
+            this.declared = atype.getDeclaredAnnotations();
+        }
+
+        @Override
+        public Type getType() {
+            return null;
+        }
+
+        @Override
+        public <T extends Annotation> T getAnnotation(@NotNull Class<T> annotation) {
+            return getDeclaredAnnotation(annotation);
+        }
+
+        @Override
+        public Annotation[] getAnnotations() {
+            return annotations;
+        }
+
+        @Override
+        public Annotation[] getDeclaredAnnotations() {
+            return declared;
+        }
+    }
 }

+ 24 - 11
assira/src/test/java/net/ranides/assira/reflection/IClassTest.java

@@ -1,17 +1,17 @@
 package net.ranides.assira.reflection;
 
-import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import net.ranides.assira.generic.SerializationUtils;
 import net.ranides.assira.generic.TypeToken;
+import net.ranides.assira.reflection.mockup.ForIClass;
 
 import java.io.IOException;
-import java.lang.reflect.Type;
 import java.util.List;
+import java.util.Map;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 public class IClassTest {
 
@@ -26,23 +26,36 @@ public class IClassTest {
         assertNotNull(SerializationUtils.copy(type2));
     }
 
-    @Ignore("todo #19")
     @Test
     public void genericSerialization() throws IOException {
         IClass<?> type2 = IClass.typeinfo(Lister.class).field("list").get().type();
-        IClass<?> type3 = new TypeToken<List<String>>() {};
+        IClass<?> type3 = IClass.typeinfo(Lister.class).field("nested").get().type();
 
-        // this lines work, but generic information is lost
-        assertNotNull(SerializationUtils.copy(type2.reflective()));
-        assertNotNull(SerializationUtils.copy(type3.reflective()));
+        IClass<?> copy2 = SerializationUtils.copy(type2);
+        assertNotNull(copy2);
+        assertEquals(type2.toString(), copy2.toString());
+        assertEquals(ForIClass.FLOAT, type2.params().get(0));
 
-        assertNotNull(SerializationUtils.copy(type2));
-        assertNotNull(SerializationUtils.copy(type3));
+        IClass<?> copy3 = SerializationUtils.copy(type3);
+        assertNotNull(copy3);
+        assertEquals(type3.toString(), copy3.toString());
+        assertEquals(ForIClass.I_NUMBER, copy3.params().get(0).params().get(1));
+    }
+
+    @Test
+    public void tokenSerialization() throws IOException {
+        IClass<?> type4 = new TypeToken<List<String>>() {};
+
+        IClass<?> copy4 = SerializationUtils.read(IClass.class, SerializationUtils.write(type4));
+        assertNotNull(copy4);
+        assertEquals(type4.toString(), copy4.toString());
+        assertEquals(ForIClass.STRING, type4.params().get(0));
     }
 
     private static final class Lister {
 
         public List<Float> list;
+        public List<Map<String, Number>> nested;
 
     }
 }