Ver Fonte

reflective

Ranides Atterwim há 10 anos atrás
pai
commit
0609e504cd

+ 1 - 1
assira/src/main/java/net/ranides/assira/generic/SerializationUtils.java

@@ -132,7 +132,7 @@ public final class SerializationUtils {
         }
 
         private Object readResolve() {
-            return IClass.typeinfo(clazz).constructors().accepts(params).first().get().call(params);
+            return IClass.typeinfo(clazz).construct(params);
         }
 
     }

+ 3 - 1
assira/src/main/java/net/ranides/assira/reflection/IClass.java

@@ -65,7 +65,9 @@ public interface IClass extends IElement, Comparable<IClass> {
      */
     Class<?> reflective();
     
-    //java.lang.reflect.Type type();
+    Object construct();
+    
+    Object construct(Object... arguments);
 	
 	/**
 	 * Checks if {@code this} is superclass of {@code type} (or equals)

+ 15 - 0
assira/src/main/java/net/ranides/assira/reflection/impl/AClass.java

@@ -9,6 +9,7 @@ package net.ranides.assira.reflection.impl;
 import java.util.Collections;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Stream;
 import net.ranides.assira.reflection.*;
@@ -24,6 +25,8 @@ public class AClass implements IClass {
     
     public static final Set<IAttribute> ATTRS = IAttribute.constant(IAttribute.FINAL, IAttribute.NATIVE, IAttribute.PUBLIC);
     
+    private final static Object[] EMPTY_ARGS = new Object[0];
+    
     protected AClass() {
         // do nothing
     }
@@ -73,6 +76,18 @@ public class AClass implements IClass {
         return AClasses.EMPTY;
     }
 
+    @Override
+    public final Object construct() {
+        return construct(EMPTY_ARGS);
+    }
+
+    @Override
+    public final Object construct(Object... arguments) {
+        return constructors()
+            .require(IAttribute.DECLARED).accepts(arguments).first().get()
+            .call(arguments);
+    }
+
     @Override
     public Class<?> reflective() {
        throw new UnsupportedOperationException("IClass<NULL> is not reflective");

+ 10 - 0
assira/src/main/java/net/ranides/assira/reflection/impl/AMethod.java

@@ -12,6 +12,7 @@ import java.util.function.Function;
 import java.util.stream.Stream;
 import net.ranides.assira.collection.iterators.IteratorUtils;
 import net.ranides.assira.reflection.*;
+import net.ranides.assira.text.StrBuilder;
 import net.ranides.assira.trace.ExceptionUtils;
 
 /**
@@ -74,5 +75,14 @@ public abstract class AMethod implements IMethod {
     public final boolean equals(Object that) {
         return (that instanceof IMethod) && 0 == compareTo((IMethod)that);
     }
+    
+    @Override
+    public String toString() {
+        return new StrBuilder()
+            .append(returns()).append(" ")
+            .append(parent())
+            .open("(", ")",", ").append(arguments().list()).close()
+            .toString();
+    }
 	
 }

+ 47 - 70
assira/src/main/java/net/ranides/assira/reflection/impl/RCompareUtils.java

@@ -51,89 +51,66 @@ public final class RCompareUtils {
         return isSuper(true, type, IClass.typefor(object));
     }
     
+    // isuper.params().equals(iclass.params())
+    //
+    // to nam załatwia "wildcards:inside" bo tak naprawdę "inside" dla wildcardów to
+    // jednoczesne super & subclass. O ile tylko dobrze je zaimplementujemy to MUSI 
+    // działać prawidłowo. Jeśli nie działa, to znaczy, że mamy zaimplementowane źle.
+    //
+    // a to oznacza też, że subclass mamy z głowy, bo dobrze zrobione "super" MUSI
+    // działać prawidłowo: anty-symetrycznie.
+    //
+    // pamiętać: RClass zachowouje się jak RWClass z upper-boundem
+    // to nam da gratis dwie metody: rw-ac oraz ac-rw
+    // wystarczy, że rw-rw prawidłowo zaimplementujemy.
+    
     private static boolean isSuper(boolean box, IClass isuper, IClass iclass) {
         if(isuper == AClass.NULL) {
             return !iclass.isPrimitive();
         }
-        boolean sw = (isuper instanceof RWClass);
-        boolean cw = (iclass instanceof RWClass);
-        if(sw && cw) {
-            return isSuper(box, (RWClass)isuper, (RWClass)iclass);
-        }
-        else if(sw && !cw) {
-            return isSuper(box, (RWClass)isuper, (AClass)iclass);
-        }
-        else if(!sw && cw) {
-            return isSuper(box, (AClass)isuper, (RWClass)iclass);
-        }
-        else {
-            return isSuper(box, (AClass)isuper, (AClass)iclass);
+        Bound sw = new Bound(isuper);
+        Bound cw = new Bound(iclass);
+        if(sw.wildcard || cw.wildcard) {
+            return isSuperBound(sw, cw);
         }
+        Class<?> sr = isuper.reflective();
+        Class<?> cr = iclass.reflective();
+        List<IClass> sp = isuper.params();
+        List<IClass> cp = iclass.params();
+        return isSuperRaw(box, sr, cr) && sp.equals(cp);
     }
     
-    private static <T extends String & CharSequence> boolean isSuper(boolean box, RWClass isuper, RWClass iclass) {
-        // czy isuper.lower isSuper iclass.upper ?
-        // czy iclass.lower isSuper isuper.upper ?
-        
-        for(IClass c : isuper.lower()) {
-            for(IClass p : iclass.upper()) {
-                if( !isSuper(c, p) ) {
-                    return false;
-                }
-            }
-        }
-        
-        for(IClass c : iclass.lower()) {
-            for(IClass p : isuper.upper()) {
-                if( !isSuper(c, p) ) {
-                    return false;
-                }
-            }
-        }
-        return isSuperList(false, isuper.params(), iclass.params());
+    private static boolean isSuperRaw(boolean box, Class<?> isuper, Class<?> iclass) {
+        return box ? ClassTraits.isSuper(isuper, iclass) : isuper.isAssignableFrom(iclass);
     }
+
     
-    private static boolean isSuper(boolean box, RWClass isuper, AClass iclass) {
-        for(IClass c : isuper.lower()) {
-            if(!isSubclass(iclass,c)) {
-                return false;
-            }
-        }
-        for(IClass c : isuper.upper()) {
-            if(!isSuper(iclass, c)) {
-                return false;
-            }
-        }
-        return isSuperList(false, isuper.params(), iclass.params());
+    private static boolean isSuperBound(Bound isuper, Bound iclass) {
+        // @todo (assira #0) reflective wildcards issuper
+        throw new UnsupportedOperationException("Not supported yet.");
+//        return isuper.params().equals(iclass.params());
     }
     
-    private static boolean isSuper(boolean box, AClass isuper, RWClass iclass) {
-        for(IClass c : iclass.lower()) {
-            if(!isSubclass(isuper,c)) {
-                return false;
-            }
-        }
-        for(IClass c : iclass.upper()) {
-            if(!isSuper(isuper, c)) {
-                return false;
+    private static class Bound {
+
+        private static final IClass[] EMPTY = new IClass[0];
+
+        final IClass[] lower;
+        final IClass[] upper;
+        final boolean wildcard;
+
+        public Bound(IClass type) {
+            if(type instanceof RWClass) {
+                this.wildcard = true;
+                this.lower = ((RWClass)type).lower();
+                this.upper = ((RWClass)type).upper();
+            } else {
+                this.wildcard = false;
+                this.lower = EMPTY;
+                this.upper = new IClass[]{type};
             }
         }
-        return isSuperList(false, isuper.params(), iclass.params());
-    }
-    
-    private static boolean isSuper(boolean box, AClass isuper, AClass iclass) {
-        if(!isSuperRaw(box, isuper.reflective(), iclass.reflective())) {
-            return false;
-        }
-        return isSuperList(box, isuper.params(), iclass.params());
-    }
-    
-    private static boolean isSuperRaw(boolean box, Class<?> isuper, Class<?> iclass) {
-        return box ? ClassTraits.isSuper(isuper, iclass) : isuper.isAssignableFrom(iclass);
-    }
-    
-    private static boolean isSuperList(boolean box, List<IClass> list1, List<IClass> list2) {
-        return ListUtils.equals(list1, list2, (a,b) -> RCompareUtils.isSuper(box,a,b));
+
     }
     
 }

+ 0 - 10
assira/src/main/java/net/ranides/assira/reflection/impl/RMethod.java

@@ -21,7 +21,6 @@ import net.ranides.assira.generic.LazyReference;
 import net.ranides.assira.reflection.*;
 import net.ranides.assira.reflection.util.MethodUtils;
 import net.ranides.assira.reflection.util.ReflectUtils;
-import net.ranides.assira.text.StrBuilder;
 import net.ranides.assira.trace.ExceptionUtils;
 
 /**
@@ -139,14 +138,5 @@ public final class RMethod extends AMethod implements IMethod {
 	public IAnnotations annotations() {
 		return new AAnnotations(AHints.EMPTY, Arrays.stream(method.getAnnotations()));
 	}
-    
-    @Override
-    public String toString() {
-        return new StrBuilder()
-            .append(returns()).append(" ")
-            .append(parent())
-            .open("(", ")",", ").append(arguments().list()).close()
-            .toString();
-    }
 
 }

+ 6 - 0
assira/src/main/java/net/ranides/assira/text/StringUtils.java

@@ -761,6 +761,12 @@ public final class StringUtils {
 		return isEmpty(value) || value.trim().isEmpty();
 	}
 	
+    /**
+     * We use Knuth–Morris–Pratt algorithm. Complexity: Θ(n)
+     * @param text
+     * @param pattern
+     * @return 
+     */
 	public static int indexOf(CharSequence text, CharSequence pattern) {
 		int[] next = initKMP(pattern);
 		

+ 46 - 0
assira/src/test/java/net/ranides/assira/reflection/impl/AClassTest.java

@@ -0,0 +1,46 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.reflection.impl;
+
+import net.ranides.assira.reflection.IAttribute;
+import net.ranides.assira.reflection.IClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class AClassTest {
+    
+    public AClassTest() {
+    }
+
+    @Test
+    public void testConstruct() {
+        IClass.typeinfo(A.class)
+            .constructors()
+            .require(IAttribute.DECLARED)
+            .accepts()
+            .stream().forEach(c -> System.out.printf("A = %s%n",c));
+        
+        IClass.typeinfo(B.class)
+            .constructors()
+            .require(IAttribute.DECLARED)
+            .stream().forEach(c -> System.out.printf("B = %s%n",c));
+
+    }
+    
+    private static class A { }
+    
+    private static class B { 
+        public B(int x) { }
+        protected B(int x, int y) { }
+        private B() { }
+    }
+    
+}

+ 26 - 12
assira/src/test/java/net/ranides/assira/reflection/impl/RCompareUtilsTest.java

@@ -27,21 +27,23 @@ public class RCompareUtilsTest {
         ForRCompareUtils u = new ForRCompareUtils();
         
         IClass ic = IClass.typeinfo(ForRCompareUtils.class);
-        IClass supA = ic.fields().require("superA").first().get().type().params().get(0);
-        IClass clsA = ic.fields().require("classA").first().get().type().params().get(0);
-        IClass extA = ic.fields().require("extenA").first().get().type().params().get(0);
+        IClass supA = ic.fields().require("superA").first().get().type();
+        IClass clsA = ic.fields().require("classA").first().get().type();
+        IClass extA = ic.fields().require("extenA").first().get().type();
         
-        System.out.printf("type = %s%n", supA.isSuper(supA) );
-        System.out.printf("type = %s%n", supA.isSuper(clsA) );
-        System.out.printf("type = %s%n", supA.isSuper(extA) );
+//        System.out.printf("%s%n", RCompareUtils. clsA.params().get(0).getClass());
+        
+        System.out.printf("type = %s%n", supA.isSubclass(supA) );
+        System.out.printf("type = %s%n", supA.isSubclass(clsA) );
+        System.out.printf("type = %s%n", supA.isSubclass(extA) );
         System.out.printf("%n");
-        System.out.printf("type = %s%n", clsA.isSuper(supA) );
-        System.out.printf("type = %s%n", clsA.isSuper(clsA) );
-        System.out.printf("type = %s%n", clsA.isSuper(extA) );
+        System.out.printf("type = %s%n", clsA.isSubclass(supA) );
+        System.out.printf("type = %s%n", clsA.isSubclass(clsA) );
+        System.out.printf("type = %s%n", clsA.isSubclass(extA) );
         System.out.printf("%n");
-        System.out.printf("type = %s%n", extA.isSuper(supA) );
-        System.out.printf("type = %s%n", extA.isSuper(clsA) );
-        System.out.printf("type = %s%n", extA.isSuper(extA) );
+        System.out.printf("type = %s%n", extA.isSubclass(supA) );
+        System.out.printf("type = %s%n", extA.isSubclass(clsA) );
+        System.out.printf("type = %s%n", extA.isSubclass(extA) );
         
         
         /*
@@ -65,6 +67,12 @@ public class RCompareUtilsTest {
          cls |  -  |  +  |  +
          ext |  +  |  +  |  +
         
+             | sup | cls | ext      issuper (2)
+        -----+-----+-----+-----
+         sup |  +  |  +  |  +
+         cls |  -  |  -  |  -
+         ext |  -  |  -  |  -
+        
         
              | sup | cls | ext      issubclass
         -----+-----+-----+-----
@@ -72,6 +80,12 @@ public class RCompareUtilsTest {
          cls |  -  |  +  |  +
          ext |  +  |  +  |  +
         
+             | sup | cls | ext      issubclass (2)
+        -----+-----+-----+-----
+         sup |  +  |  -  |  -
+         cls |  -  |  -  |  -
+         ext |  -  |  -  |  -
+        
         // @todo (assira #5) reflective compare
         
         Dobra. Zaimplementowaliśmy istotnie coś, co chcielśmy.