新增工具类ToStringBuilder,抽象Cache类
parent
c305df04b9
commit
2b6ecfcf1e
|
@ -1,30 +1,18 @@
|
|||
package io.github.yezhihao.protostar.schema;
|
||||
|
||||
import io.github.yezhihao.protostar.Schema;
|
||||
import io.github.yezhihao.protostar.util.Cache;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CollectionSchema<T> implements Schema<List<T>> {
|
||||
|
||||
private static volatile Map<Object, CollectionSchema> cache = new HashMap<>();
|
||||
private static final Cache<Schema, CollectionSchema> CACHE = new Cache<>();
|
||||
|
||||
public static Schema<List> getInstance(Schema schema) {
|
||||
Object key = schema;
|
||||
CollectionSchema instance;
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
synchronized (cache) {
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
instance = new CollectionSchema(schema);
|
||||
cache.put(schema, instance);
|
||||
log.debug("new CollectionSchema({})", schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
public static CollectionSchema getInstance(Schema schema) {
|
||||
return CACHE.get(schema, key -> new CollectionSchema(key));
|
||||
}
|
||||
|
||||
private final Schema<T> schema;
|
||||
|
|
|
@ -2,36 +2,24 @@ package io.github.yezhihao.protostar.schema;
|
|||
|
||||
import io.github.yezhihao.protostar.Schema;
|
||||
import io.github.yezhihao.protostar.converter.Converter;
|
||||
import io.github.yezhihao.protostar.util.Cache;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义结构转换
|
||||
*/
|
||||
public class ConvertSchema<T> implements Schema<T> {
|
||||
|
||||
private static volatile Map<Object, ConvertSchema> cache = new HashMap<>();
|
||||
private static final Cache<String, ConvertSchema> cache = new Cache<>();
|
||||
|
||||
public static Schema getInstance(Class<? extends Converter> clazz) {
|
||||
String key = clazz.getName();
|
||||
ConvertSchema instance;
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
synchronized (cache) {
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
try {
|
||||
Converter converter = clazz.newInstance();
|
||||
instance = new ConvertSchema(converter);
|
||||
cache.put(key, instance);
|
||||
log.debug("new ConvertSchema({})", clazz);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public static ConvertSchema getInstance(Class<? extends Converter> clazz) {
|
||||
return cache.get(clazz.getName(), key -> {
|
||||
try {
|
||||
return new ConvertSchema(clazz.newInstance());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
});
|
||||
}
|
||||
|
||||
private final Converter<T> converter;
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
package io.github.yezhihao.protostar.schema;
|
||||
|
||||
import io.github.yezhihao.protostar.Schema;
|
||||
import io.github.yezhihao.protostar.util.Cache;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ObjectSchema<T> implements Schema<T> {
|
||||
|
||||
private static volatile Map<Object, ObjectSchema> cache = new HashMap<>();
|
||||
private static final Cache<Schema, ObjectSchema> cache = new Cache<>();
|
||||
|
||||
public static Schema getInstance(Schema schema) {
|
||||
Object key = schema;
|
||||
ObjectSchema instance;
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
synchronized (cache) {
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
instance = new ObjectSchema(schema);
|
||||
cache.put(schema, instance);
|
||||
log.debug("new ObjectSchema({})", schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
public static ObjectSchema getInstance(Schema schema) {
|
||||
return cache.get(schema, key -> new ObjectSchema(key));
|
||||
}
|
||||
|
||||
private final Schema<T> schema;
|
||||
|
|
|
@ -2,32 +2,20 @@ package io.github.yezhihao.protostar.schema;
|
|||
|
||||
import io.github.yezhihao.protostar.Schema;
|
||||
import io.github.yezhihao.protostar.util.Bcd;
|
||||
import io.github.yezhihao.protostar.util.Cache;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StringSchema {
|
||||
|
||||
public static class Chars implements Schema<String> {
|
||||
private static volatile Map<Object, Chars> cache = new HashMap<>();
|
||||
private static final Cache<String, Chars> cache = new Cache<>();
|
||||
|
||||
public static Schema<String> getInstance(byte pad, String charset) {
|
||||
charset = charset.toLowerCase();
|
||||
String key = new StringBuilder(10).append((char) pad).append('/').append(charset).toString();
|
||||
Chars instance;
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
synchronized (cache) {
|
||||
if ((instance = cache.get(key)) == null) {
|
||||
instance = new Chars(pad, charset);
|
||||
cache.put(key, instance);
|
||||
log.debug("new StringSchema({},{})", pad, charset);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
public static Chars getInstance(final byte pad, final String charset) {
|
||||
String key = new StringBuilder(10).append((char) pad).append('/').append(charset.toLowerCase()).toString();
|
||||
return cache.get(key, k -> new Chars(pad, charset));
|
||||
}
|
||||
|
||||
private final byte pad;
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package io.github.yezhihao.protostar.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author yezhihao
|
||||
* home https://gitee.com/yezhihao/jt808-server
|
||||
*/
|
||||
public class Cache<K, V> {
|
||||
|
||||
private volatile HashMap<K, V> cache;
|
||||
|
||||
public Cache() {
|
||||
this(32);
|
||||
}
|
||||
|
||||
public Cache(int initialCapacity) {
|
||||
this.cache = new HashMap<>((int) (initialCapacity / 0.75) + 1);
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
return cache.get(key);
|
||||
}
|
||||
|
||||
public V get(K key, Function<K, V> function) {
|
||||
V value = cache.get(key);
|
||||
if (value == null) {
|
||||
synchronized (cache) {
|
||||
value = cache.get(key);
|
||||
if (value == null) {
|
||||
cache.put(key, value = function.apply(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return cache.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package io.github.yezhihao.protostar.util;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* @author yezhihao
|
||||
* home https://gitee.com/yezhihao/jt808-server
|
||||
*/
|
||||
public class ToStringBuilder {
|
||||
|
||||
private static Cache<String, Builder[]> CACHE = new Cache<>();
|
||||
|
||||
public static String toString(Object object) {
|
||||
return toString(null, object, true, (String[]) null);
|
||||
}
|
||||
|
||||
public static String toString(Object object, boolean superclass, String... ignores) {
|
||||
return toString(null, object, superclass, ignores);
|
||||
}
|
||||
|
||||
public static String toString(StringBuilder sb, Object object, boolean superclass, String... ignores) {
|
||||
Class<?> typeClass = object.getClass();
|
||||
Builder[] builders = getBuilders(typeClass, ignores);
|
||||
if (sb == null)
|
||||
sb = new StringBuilder(builders.length * 10);
|
||||
|
||||
String name = typeClass.getName();
|
||||
sb.append(name, name.lastIndexOf('.') + 1, name.length());
|
||||
sb.append('{');
|
||||
try {
|
||||
if (superclass) {
|
||||
for (Builder builder : builders)
|
||||
builder.append(sb, object);
|
||||
} else {
|
||||
for (Builder builder : builders)
|
||||
if (!builder.superclass)
|
||||
builder.append(sb, object);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
sb.setCharAt(sb.length() - 1, '}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static Builder[] getBuilders(Class<?> typeClass, String... ignores) {
|
||||
return CACHE.get(typeClass.getName(), s -> {
|
||||
Method[] methods = typeClass.getMethods();
|
||||
ArrayList<Builder> result = new ArrayList<>(methods.length);
|
||||
|
||||
for (Method method : methods) {
|
||||
String mName = method.getName();
|
||||
String name = getName(mName);
|
||||
if ((mName.startsWith("get") || mName.startsWith("is")) &&
|
||||
!"class".equals(name) &&
|
||||
!contains(ignores, name) &&
|
||||
method.getParameterCount() == 0 && !method.isAnnotationPresent(Transient.class))
|
||||
result.add(new Builder(name, method, !typeClass.equals(method.getDeclaringClass())));
|
||||
}
|
||||
|
||||
Builder[] temp = new Builder[result.size()];
|
||||
result.toArray(temp);
|
||||
Arrays.sort(temp);
|
||||
return temp;
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean contains(Object[] array, Object obj) {
|
||||
if (array == null || array.length == 0 || obj == null)
|
||||
return false;
|
||||
for (Object t : array) {
|
||||
if (obj.equals(t))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getName(String methodName) {
|
||||
char[] name = methodName.toCharArray();
|
||||
if (name[0] == 'g') {
|
||||
name[3] += 32;
|
||||
return new String(name, 3, name.length - 3);
|
||||
} else {
|
||||
name[2] += 32;
|
||||
return new String(name, 2, name.length - 2);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Builder implements Comparable<Builder> {
|
||||
private static final BiConsumer<StringBuilder, Object> APPEND_OBJ = (sb, obj) -> sb.append(obj);
|
||||
private static final BiConsumer<StringBuilder, Object> APPEND_ARRAY = (sb, array) -> {
|
||||
sb.append('[');
|
||||
int length = Array.getLength(array);
|
||||
boolean tooLong = length > 140;
|
||||
length = tooLong ? 140 : length;
|
||||
for (int i = 0; i < length; i++)
|
||||
sb.append(Array.get(array, i)).append(',');
|
||||
if (tooLong)
|
||||
sb.append("......");
|
||||
sb.setCharAt(sb.length() - 1, ']');
|
||||
};
|
||||
|
||||
public final String name;
|
||||
public final boolean superclass;
|
||||
private final Method method;
|
||||
private final BiConsumer<StringBuilder, Object> append;
|
||||
|
||||
public void append(StringBuilder sb, Object obj) throws Exception {
|
||||
Object value = method.invoke(obj);
|
||||
if (value != null) {
|
||||
sb.append(name).append('=');
|
||||
append.accept(sb, value);
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
|
||||
public Builder(String name, Method method, boolean superclass) {
|
||||
this.name = name;
|
||||
this.method = method;
|
||||
this.superclass = superclass;
|
||||
if (method.getReturnType().isArray()) {
|
||||
append = APPEND_ARRAY;
|
||||
} else {
|
||||
append = APPEND_OBJ;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Builder that) {
|
||||
Class<?> thatType = that.method.getReturnType();
|
||||
if (Iterable.class.isAssignableFrom(thatType) || thatType.isArray())
|
||||
return -1;
|
||||
Class<?> thisType = this.method.getReturnType();
|
||||
if (Iterable.class.isAssignableFrom(thisType) || thisType.isArray())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue