mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-25 11:51:15 +08:00
convert query path to match pattern
This commit is contained in:
parent
bdd16c0948
commit
a5038320b4
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user