convert query path to match pattern

This commit is contained in:
金戟 2021-03-16 11:50:22 +08:00
parent bdd16c0948
commit a5038320b4
5 changed files with 104 additions and 22 deletions

View File

@ -1,6 +1,7 @@
package com.alibaba.testable.core.tool;
import com.alibaba.testable.core.util.UnnullableMap;
import com.alibaba.testable.core.util.FixSizeMap;
import com.sun.deploy.util.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
@ -14,7 +15,7 @@ import static com.alibaba.testable.core.constant.ConstPool.SLASH;
*/
public class OmniAccessor {
private static final UnnullableMap<Class<?>, List<String>> MEMBER_INDEXES = UnnullableMap.of(new ArrayList<String>());
private static final FixSizeMap<Class<?>, List<String>> MEMBER_INDEXES = new FixSizeMap<Class<?>, List<String>>(30);
private static final String THIS_REF_PREFIX = "this$";
/**
@ -54,16 +55,19 @@ public class OmniAccessor {
* @param target 目标对象
* @param queryPath 搜索路径
* @param value 新的值
* @return 实际影响的成员个数
*/
public static void set(Object target, String queryPath, Object value) {
public static int set(Object target, String queryPath, Object value) {
int count = 0;
for (String memberPath : MEMBER_INDEXES.getOrElse(target.getClass(), generateMemberIndex(target.getClass()))) {
if (memberPath.matches(toPattern(queryPath))) {
Object parent = getByPath(target, toParent(memberPath));
if (parent != null) {
setByPath(parent, toChild(memberPath), value);
if (parent != null && setByPath(parent, toChild(memberPath), value)) {
count++;
}
}
}
return count;
}
private static List<String> generateMemberIndex(Class<?> clazz) {
@ -84,9 +88,10 @@ public class OmniAccessor {
}
private static List<Field> getAllFields(Class<?> clazz) {
List<Field> fields = new ArrayList<Field>(Arrays.asList(clazz.getDeclaredFields()));
if (clazz.getSuperclass() != null) {
fields.addAll(getAllFields(clazz.getSuperclass()));
Class<?> rawClass = clazz.isArray() ? clazz.getComponentType() : clazz;
List<Field> fields = new ArrayList<Field>(Arrays.asList(rawClass.getDeclaredFields()));
if (rawClass.getSuperclass() != null) {
fields.addAll(getAllFields(rawClass.getSuperclass()));
}
return fields;
}
@ -96,7 +101,23 @@ public class OmniAccessor {
}
private static String toPattern(String queryPath) {
return "";
String[] querySegments = queryPath.split(SLASH);
String[] patternSegments = new String[querySegments.length];
for (int i = 0; i < querySegments.length; i++) {
patternSegments[i] = toSinglePattern(querySegments[i]);
}
return StringUtils.join(Arrays.asList(patternSegments), SLASH);
}
private static String toSinglePattern(String querySegment) {
if (querySegment.isEmpty()) {
return "";
} else if (querySegment.startsWith("{")) {
return "[^{]+" + querySegment.replace("{", "\\{").replace("}", "\\}")
.replace("[", "\\[").replace("]", "\\]");
} else {
return querySegment + "\\{[^}]+\\}";
}
}
private static String toChild(String memberPath) {
@ -111,8 +132,8 @@ public class OmniAccessor {
return null;
}
private static void setByPath(Object target, String memberPath, Object value) {
private static boolean setByPath(Object target, String memberPath, Object value) {
return true;
}
}

View File

@ -0,0 +1,45 @@
package com.alibaba.testable.core.util;
import com.sun.tools.javac.util.ListBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
/**
* @author flin
*/
public class FixSizeMap<K, V> {
private final int capacity;
private final Map<K, V> content;
private final Queue<K> order;
public FixSizeMap(int size) {
this.capacity = size;
this.content = new HashMap<K, V>(size);
this.order = new ListBuffer<K>();
}
public V get(K key) {
return content.get(key);
}
public void put(K key, V value) {
if (order.size() >= capacity) {
content.remove(order.poll());
}
order.add(key);
content.put(key, value);
}
public V getOrElse(K key, V elseValue) {
V value = get(key);
if (value == null) {
value = elseValue;
put(key, value);
}
return value;
}
}

View File

@ -2,9 +2,9 @@ package com.alibaba.testable.core.tool;
public class DemoChild {
public DemoGrandChild gc1;
public DemoGrandChild gc;
private DemoGrandChild gc2;
private DemoGrandChild[] gcs;
public class SubChild {
private DemoGrandChild gc;

View File

@ -2,9 +2,9 @@ package com.alibaba.testable.core.tool;
public class DemoParent {
private DemoChild c1;
private DemoChild c;
public DemoChild c2;
public DemoChild[] cs;
public DemoChild.SubChild sc;

View File

@ -13,12 +13,12 @@ class OmniAccessorTest {
void should_generate_member_index() {
List<String> index = PrivateAccessor.invokeStatic(OmniAccessor.class, "generateMemberIndex", DemoParent.class);
assertEquals(10, index.size());
assertEquals("/c1{DemoChild}", index.get(0));
assertEquals("/c1{DemoChild}/gc1{DemoGrandChild}", index.get(1));
assertEquals("/c1{DemoChild}/gc2{DemoGrandChild}", index.get(2));
assertEquals("/c2{DemoChild}", index.get(3));
assertEquals("/c2{DemoChild}/gc1{DemoGrandChild}", index.get(4));
assertEquals("/c2{DemoChild}/gc2{DemoGrandChild}", index.get(5));
assertEquals("/c{DemoChild}", index.get(0));
assertEquals("/c{DemoChild}/gc{DemoGrandChild}", index.get(1));
assertEquals("/c{DemoChild}/gcs{DemoGrandChild[]}", index.get(2));
assertEquals("/cs{DemoChild[]}", index.get(3));
assertEquals("/cs{DemoChild[]}/gc{DemoGrandChild}", index.get(4));
assertEquals("/cs{DemoChild[]}/gcs{DemoGrandChild[]}", index.get(5));
assertEquals("/sc{SubChild}", index.get(6));
assertEquals("/sc{SubChild}/gc{DemoGrandChild}", index.get(7));
assertEquals("/ssc{StaticSubChild}", index.get(8));
@ -26,8 +26,24 @@ class OmniAccessorTest {
}
@Test
void should_to_pattern() {
void should_match_pattern() {
assertTrue("abc{Abc}".matches("abc\\{[^}]+\\}"));
assertTrue("abc{Abc}".matches("[^{]+\\{Abc\\}"));
assertTrue("abc{Abc[]}/xyz{Xyz[]}".matches("[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}"));
assertTrue("abc{Abc}/xyz{Xyz}/demo{Demo}".matches("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}"));
}
@Test
void should_to_pattern() {
assertEquals("", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", ""));
assertEquals("abc\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc"));
assertEquals("[^{]+\\{Abc\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}"));
assertEquals("abc\\{[^}]+\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/xyz"));
assertEquals("[^{]+\\{Abc\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/xyz"));
assertEquals("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}"));
assertEquals("[^{]+\\{Abc\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/{Xyz}"));
assertEquals("[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc[]}/{Xyz[]}"));
assertEquals("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}/demo"));
}
@Test