From 206fc5486e576fcef6f330d4b279e2afba2c2e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=91=E6=88=9F?= Date: Thu, 18 Mar 2021 00:15:01 +0800 Subject: [PATCH] support access array element by index --- .../testable/core/tool/OmniAccessor.java | 23 +++++++++-- .../testable/core/tool/OmniConstructor.java | 38 +++++++++++------- .../testable/core/tool/DemoGrandChild.java | 9 +++++ .../testable/core/tool/DemoParent.java | 6 +-- .../testable/core/tool/OmniAccessorTest.java | 40 ++++++++++++++++--- 5 files changed, 90 insertions(+), 26 deletions(-) diff --git a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniAccessor.java b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniAccessor.java index 47dc3b3..df8d617 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniAccessor.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniAccessor.java @@ -4,6 +4,7 @@ import com.alibaba.testable.core.util.FixSizeMap; import com.alibaba.testable.core.util.TypeUtil; import com.sun.deploy.util.StringUtils; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; @@ -147,7 +148,7 @@ public class OmniAccessor { private static int extraIndexFromQuery(String query) { return query.endsWith(BRACKET_END) - ? Integer.parseInt(query.substring(query.lastIndexOf(BRACKET_START) + 1), query.length() - 1) + ? Integer.parseInt(query.substring(query.lastIndexOf(BRACKET_START) + 1, query.length() - 1)) : -1; } @@ -165,7 +166,12 @@ public class OmniAccessor { nth = extraIndexFromQuery(querySegments[i]); field = TypeUtil.getFieldByName(obj.getClass(), name); field.setAccessible(true); - obj = field.get(obj); + if (field.getType().isArray() && nth >= 0) { + Object f = field.get(obj); + obj = Array.get(f, nth); + } else { + obj = field.get(obj); + } } return obj; } @@ -176,7 +182,18 @@ public class OmniAccessor { int nth = extraIndexFromQuery(querySegment); Field field = TypeUtil.getFieldByName(target.getClass(), name); field.setAccessible(true); - field.set(target, value); + if (field.getType().isArray()) { + Object f = field.get(target); + if (nth >= 0) { + Array.set(f, nth, value); + } else { + for (int i = 0; i < Array.getLength(f); i++) { + Array.set(f, i, value); + } + } + } else { + field.set(target, value); + } } } diff --git a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java index 23a58b5..b9afea8 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java @@ -3,10 +3,7 @@ package com.alibaba.testable.core.tool; import com.alibaba.testable.core.model.Null; import com.alibaba.testable.core.util.TypeUtil; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.*; /** * @author flin @@ -19,9 +16,14 @@ public class OmniConstructor { return newPrimitive(clazz); } else if (clazz.isArray()) { return newArray(clazz); - } else { - return newObject(clazz); + } else if (clazz.isEnum()) { + return newEnum(clazz); + } else if (clazz.isInterface()) { + return newInterface(clazz); + } else if (Modifier.isAbstract(clazz.getModifiers())) { + return newAbstractClass(clazz); } + return newObject(clazz); } catch (NoSuchMethodException e) { return null; } catch (IllegalAccessException e) { @@ -30,17 +32,11 @@ public class OmniConstructor { return null; } catch (InvocationTargetException e) { return null; + } catch (ClassCastException e) { + return null; } } - public static void appendInstance(Object target, Class clazz) { - appendInstance(target, 1, clazz); - } - - public static void appendInstance(Object target, int count, Class clazz) { - return; - } - private static T newObject(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Constructor constructor = getBestConstructor(clazz); @@ -53,6 +49,20 @@ public class OmniConstructor { return (T)ins; } + private static T newAbstractClass(Class clazz) { + return null; + } + + private static T newInterface(Class clazz) { + return null; + } + + private static T newEnum(Class clazz) + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + T[] constants = clazz.getEnumConstants(); + return constants.length > 0 ? constants[0] : null; + } + private static T newArray(Class clazz) { return (T)Array.newInstance(clazz.getComponentType(), 0); } diff --git a/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoGrandChild.java b/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoGrandChild.java index 7bd709f..3226fac 100644 --- a/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoGrandChild.java +++ b/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoGrandChild.java @@ -7,4 +7,13 @@ public class DemoGrandChild { public DemoGrandChild(int i) { this.i = i; } + + public int get() { + return i; + } + + public void set(int i) { + this.i = i; + } + } diff --git a/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoParent.java b/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoParent.java index 62c9396..4d80b92 100644 --- a/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoParent.java +++ b/testable-core/src/test/java/com/alibaba/testable/core/tool/DemoParent.java @@ -4,10 +4,10 @@ public class DemoParent { public DemoChild c; - private DemoChild[] cs; + public DemoChild[] cs; - public DemoChild.SubChild sc; + private DemoChild.SubChild sc; - public DemoChild.StaticSubChild ssc; + private DemoChild.StaticSubChild ssc; } diff --git a/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java b/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java index e4f8e93..30e2c80 100644 --- a/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java +++ b/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java @@ -73,21 +73,49 @@ class OmniAccessorTest { @Test void should_get_by_path() { - DemoParent parent = prepareDemoObject(); + DemoParent parent = prepareParentObject(); Object obj = PrivateAccessor.invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc"); assertTrue(obj instanceof DemoGrandChild); - assertEquals(0, PrivateAccessor.get(obj, "i")); + assertEquals(0, ((DemoGrandChild)obj).get()); + PrivateAccessor.set(parent.c, "gcs", new DemoGrandChild[] { new DemoGrandChild(4), new DemoGrandChild(6) }); + obj = PrivateAccessor.invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs"); + assertTrue(obj instanceof DemoGrandChild[]); + assertEquals(2, ((DemoGrandChild[])obj).length); + obj = PrivateAccessor.invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs[1]"); + assertTrue(obj instanceof DemoGrandChild); + assertEquals(6, ((DemoGrandChild)obj).get()); + parent.cs = new DemoChild[] { null, prepareChildObject() }; + obj = PrivateAccessor.invokeStatic(OmniAccessor.class, "getByPath", parent, "cs{DemoChild[]}/gcs{DemoGrandChild[]}/i{int}", "c[1]/gcs[1]/i"); + assertEquals(3, obj); } @Test void should_set_by_path_segment() { - DemoParent parent = prepareDemoObject(); + DemoParent parent = prepareParentObject(); + DemoChild child = prepareChildObject(); PrivateAccessor.invokeStatic(OmniAccessor.class, "setByPathSegment", parent.c, "gc{DemoGrandChild}", "gc", new DemoGrandChild(2)); - assertEquals(2, PrivateAccessor.get(parent.c.gc, "i")); + assertEquals(2, parent.c.gc.get()); + PrivateAccessor.invokeStatic(OmniAccessor.class, "setByPathSegment", parent, "cs{DemoChild[]}", "cs[2]", child); + assertNull(parent.cs[0]); + assertNull(parent.cs[1]); + assertEquals(5, parent.cs[2].gc.get()); + PrivateAccessor.invokeStatic(OmniAccessor.class, "setByPathSegment", parent, "cs{DemoChild[]}", "cs", child); + assertEquals(5, parent.cs[0].gc.get()); + assertEquals(5, parent.cs[1].gc.get()); + assertEquals(5, parent.cs[2].gc.get()); } - private DemoParent prepareDemoObject() { - return OmniConstructor.newInstance(DemoParent.class); + private DemoParent prepareParentObject() { + DemoParent parent = OmniConstructor.newInstance(DemoParent.class); + parent.cs = new DemoChild[3]; + return parent; + } + + private DemoChild prepareChildObject() { + DemoChild child = OmniConstructor.newInstance(DemoChild.class); + PrivateAccessor.set(child, "gcs", new DemoGrandChild[] { null, new DemoGrandChild(3) }); + child.gc.set(5); + return child; } }