All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkale.convert.ConvertFactory Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkale.convert;

import java.io.File;
import java.lang.reflect.*;
import java.math.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.*;
import java.util.regex.Pattern;
import java.util.stream.*;
import org.redkale.convert.ext.*;
import org.redkale.util.*;

/**
 * 序列化模块的工厂类,用于注册自定义的序列化类型,获取Convert
 *
 * 

* 详情见: https://redkale.org * * @author zhangjx * @param Reader输入的子类 * @param Writer输出的子类 */ @SuppressWarnings("unchecked") public abstract class ConvertFactory { private final ConvertFactory parent; protected Convert convert; protected boolean tiny; private final Encodeable anyEncoder = new AnyEncoder(this); //----------------------------------------------------------------------------------- private final ConcurrentHashMap creators = new ConcurrentHashMap(); private final ConcurrentHashMap entitys = new ConcurrentHashMap(); private final ConcurrentHashMap>> fieldCoders = new ConcurrentHashMap(); private final ConcurrentHashMap> decoders = new ConcurrentHashMap(); private final ConcurrentHashMap> encoders = new ConcurrentHashMap(); private final ConcurrentHashMap columnEntrys = new ConcurrentHashMap(); private final Set skipIgnores = new HashSet(); //key:需要屏蔽的字段;value:排除的字段名 private final ConcurrentHashMap> ignoreAlls = new ConcurrentHashMap(); private boolean skipAllIgnore = false; protected ConvertFactory(ConvertFactory parent, boolean tiny) { this.tiny = tiny; this.parent = parent; if (parent == null) { //--------------------------------------------------------- this.register(boolean.class, BoolSimpledCoder.instance); this.register(Boolean.class, BoolSimpledCoder.instance); this.register(byte.class, ByteSimpledCoder.instance); this.register(Byte.class, ByteSimpledCoder.instance); this.register(short.class, ShortSimpledCoder.instance); this.register(Short.class, ShortSimpledCoder.instance); this.register(char.class, CharSimpledCoder.instance); this.register(Character.class, CharSimpledCoder.instance); this.register(int.class, IntSimpledCoder.instance); this.register(Integer.class, IntSimpledCoder.instance); this.register(long.class, LongSimpledCoder.instance); this.register(Long.class, LongSimpledCoder.instance); this.register(float.class, FloatSimpledCoder.instance); this.register(Float.class, FloatSimpledCoder.instance); this.register(double.class, DoubleSimpledCoder.instance); this.register(Double.class, DoubleSimpledCoder.instance); this.register(Number.class, NumberSimpledCoder.instance); this.register(String.class, StringSimpledCoder.instance); this.register(CharSequence.class, CharSequenceSimpledCoder.instance); this.register(java.util.Date.class, DateSimpledCoder.instance); this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance); this.register(AtomicLong.class, AtomicLongSimpledCoder.instance); this.register(BigInteger.class, BigIntegerSimpledCoder.instance); this.register(BigDecimal.class, BigDecimalSimpledCoder.instance); this.register(InetAddress.class, InetAddressSimpledCoder.instance); this.register(DLong.class, DLongSimpledCoder.instance); this.register(Class.class, TypeSimpledCoder.instance); this.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressSimpledCoder.instance); this.register(Pattern.class, PatternSimpledCoder.instance); this.register(File.class, FileSimpledCoder.instance); this.register(CompletionHandler.class, CompletionHandlerSimpledCoder.instance); this.register(URL.class, URLSimpledCoder.instance); this.register(URI.class, URISimpledCoder.instance); //--------------------------------------------------------- this.register(ByteBuffer.class, ByteBufferSimpledCoder.instance); this.register(boolean[].class, BoolArraySimpledCoder.instance); this.register(byte[].class, ByteArraySimpledCoder.instance); this.register(short[].class, ShortArraySimpledCoder.instance); this.register(char[].class, CharArraySimpledCoder.instance); this.register(int[].class, IntArraySimpledCoder.instance); this.register(IntStream.class, IntArraySimpledCoder.IntStreamSimpledCoder.instance); this.register(long[].class, LongArraySimpledCoder.instance); this.register(LongStream.class, LongArraySimpledCoder.LongStreamSimpledCoder.instance); this.register(float[].class, FloatArraySimpledCoder.instance); this.register(double[].class, DoubleArraySimpledCoder.instance); this.register(DoubleStream.class, DoubleArraySimpledCoder.DoubleStreamSimpledCoder.instance); this.register(String[].class, StringArraySimpledCoder.instance); //--------------------------------------------------------- this.register(AnyValue.class, Creator.create(AnyValue.DefaultAnyValue.class)); this.register(HttpCookie.class, new Creator() { @Override @ConstructorParameters({"name", "value"}) public HttpCookie create(Object... params) { return new HttpCookie((String) params[0], (String) params[1]); } }); } } public ConvertFactory parent() { return this.parent; } public abstract ConvertType getConvertType(); public abstract boolean isReversible(); //是否可逆的 public abstract boolean isFieldSort(); //当ConvertColumn.index相同时是否按字段名称排序 public abstract ConvertFactory createChild(); public abstract ConvertFactory createChild(boolean tiny); protected SimpledCoder createEnumSimpledCoder(Class enumClass) { return new EnumSimpledCoder(enumClass); } protected ObjectDecoder createObjectDecoder(Type type) { return new ObjectDecoder(type); } protected ObjectEncoder createObjectEncoder(Type type) { return new ObjectEncoder(type); } protected Decodeable createMapDecoder(Type type) { return new MapDecoder(this, type); } protected Encodeable createMapEncoder(Type type) { return new MapEncoder(this, type); } protected Decodeable createArrayDecoder(Type type) { return new ArrayDecoder(this, type); } protected Encodeable createArrayEncoder(Type type) { return new ArrayEncoder(this, type); } protected Decodeable createCollectionDecoder(Type type) { return new CollectionDecoder(this, type); } protected Encodeable createCollectionEncoder(Type type) { return new CollectionEncoder(this, type); } protected Decodeable createStreamDecoder(Type type) { return new StreamDecoder(this, type); } protected Encodeable createStreamEncoder(Type type) { return new StreamEncoder(this, type); } public Convert getConvert() { return convert; } public ConvertFactory tiny(boolean tiny) { this.tiny = tiny; return this; } public boolean isConvertDisabled(AccessibleObject element) { ConvertDisabled[] ccs = element.getAnnotationsByType(ConvertDisabled.class); if (ccs.length == 0 && element instanceof Method) { final Method method = (Method) element; String fieldName = readGetSetFieldName(method); if (fieldName != null) { try { ccs = method.getDeclaringClass().getDeclaredField(fieldName).getAnnotationsByType(ConvertDisabled.class); } catch (Exception e) { //说明没有该字段,忽略异常 } } } final ConvertType ct = this.getConvertType(); for (ConvertDisabled ref : ccs) { if (ref.type().contains(ct)) return true; } return false; } public ConvertColumnEntry findRef(AccessibleObject element) { if (element == null) return null; ConvertColumnEntry en = this.columnEntrys.get(element); Set onlyColumns = null; if (element instanceof Method) { onlyColumns = ignoreAlls.get(((Method) element).getDeclaringClass()); } else if (element instanceof Field) { onlyColumns = ignoreAlls.get(((Field) element).getDeclaringClass()); } if (en != null && onlyColumns == null) return en; final ConvertType ct = this.getConvertType(); ConvertColumn[] ccs = element.getAnnotationsByType(ConvertColumn.class); String fieldName = null; if (ccs.length == 0 && element instanceof Method) { final Method method = (Method) element; fieldName = readGetSetFieldName(method); if (fieldName != null) { try { ccs = method.getDeclaringClass().getDeclaredField(fieldName).getAnnotationsByType(ConvertColumn.class); } catch (Exception e) { //说明没有该字段,忽略异常 } } } if (onlyColumns != null && fieldName == null) { if (element instanceof Method) { fieldName = readGetSetFieldName((Method) element); } else if (element instanceof Field) { fieldName = ((Field) element).getName(); } } if (ccs.length == 0 && onlyColumns != null && fieldName != null) { if (!onlyColumns.contains(fieldName)) return new ConvertColumnEntry(fieldName, true); } for (ConvertColumn ref : ccs) { if (ref.type().contains(ct)) { if (onlyColumns != null && fieldName != null) { String realName = ref.name().isEmpty() ? fieldName : ref.name(); if (!onlyColumns.contains(realName)) return new ConvertColumnEntry(realName, true); } ConvertColumnEntry entry = new ConvertColumnEntry(ref); if (skipAllIgnore) { entry.setIgnore(false); return entry; } if (skipIgnores.isEmpty()) return entry; if (skipIgnores.contains(((Member) element).getDeclaringClass())) entry.setIgnore(false); return entry; } } return null; } static String readGetSetFieldName(Method method) { if (method == null) return null; String fname = method.getName(); if (!fname.startsWith("is") && !fname.startsWith("get") && !fname.startsWith("set")) return fname; fname = fname.substring(fname.startsWith("is") ? 2 : 3); if (fname.length() > 1 && !(fname.charAt(1) >= 'A' && fname.charAt(1) <= 'Z')) { fname = Character.toLowerCase(fname.charAt(0)) + fname.substring(1); } else if (fname.length() == 1) { fname = "" + Character.toLowerCase(fname.charAt(0)); } return fname; } final String getEntityAlias(Class clazz) { if (clazz == String.class) return "A"; if (clazz == int.class) return "I"; if (clazz == Integer.class) return "i"; if (clazz == long.class) return "J"; if (clazz == Long.class) return "j"; if (clazz == byte.class) return "B"; if (clazz == Byte.class) return "b"; if (clazz == boolean.class) return "Z"; if (clazz == Boolean.class) return "z"; if (clazz == short.class) return "S"; if (clazz == Short.class) return "s"; if (clazz == char.class) return "C"; if (clazz == Character.class) return "c"; if (clazz == float.class) return "F"; if (clazz == Float.class) return "f"; if (clazz == double.class) return "D"; if (clazz == Double.class) return "d"; if (clazz == String[].class) return "[A"; if (clazz == int[].class) return "[I"; if (clazz == long[].class) return "[J"; if (clazz == byte[].class) return "[B"; if (clazz == boolean[].class) return "[Z"; if (clazz == short[].class) return "[S"; if (clazz == char[].class) return "[C"; if (clazz == float[].class) return "[F"; if (clazz == double[].class) return "[D"; ConvertEntity ce = (ConvertEntity) clazz.getAnnotation(ConvertEntity.class); if (ce != null && findEntityAlias(ce.value()) == null) entitys.put(ce.value(), clazz); return ce == null ? clazz.getName() : ce.value(); } final Class getEntityAlias(String name) { if ("A".equals(name)) return String.class; if ("I".equals(name)) return int.class; if ("i".equals(name)) return Integer.class; if ("J".equals(name)) return long.class; if ("j".equals(name)) return Long.class; if ("B".equals(name)) return byte.class; if ("b".equals(name)) return Byte.class; if ("Z".equals(name)) return boolean.class; if ("z".equals(name)) return Boolean.class; if ("S".equals(name)) return short.class; if ("s".equals(name)) return Short.class; if ("C".equals(name)) return char.class; if ("c".equals(name)) return Character.class; if ("F".equals(name)) return float.class; if ("f".equals(name)) return Float.class; if ("D".equals(name)) return double.class; if ("d".equals(name)) return Double.class; if ("[A".equals(name)) return String[].class; if ("[I".equals(name)) return int[].class; if ("[J".equals(name)) return long[].class; if ("[B".equals(name)) return byte[].class; if ("[Z".equals(name)) return boolean[].class; if ("[S".equals(name)) return short[].class; if ("[C".equals(name)) return char[].class; if ("[F".equals(name)) return float[].class; if ("[D".equals(name)) return double[].class; Class clazz = findEntityAlias(name); try { return clazz == null ? Thread.currentThread().getContextClassLoader().loadClass(name) : clazz; } catch (Exception ex) { throw new ConvertException("convert entity is " + name, ex); } } private Class findEntityAlias(String name) { Class clazz = entitys.get(name); return parent == null ? clazz : parent.findEntityAlias(name); } /** * 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false * * @param skipIgnore 是否忽略Ignore注解 */ public final void registerSkipAllIgnore(final boolean skipIgnore) { this.skipAllIgnore = skipIgnore; } /** * 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false * * @param skipIgnore 忽略ignore * * @return 自身 */ public ConvertFactory skipAllIgnore(final boolean skipIgnore) { this.skipAllIgnore = skipIgnore; return this; } /** * 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false * * @param type 指定的类 */ public final void registerSkipIgnore(final Class type) { skipIgnores.add(type); } /** * 屏蔽指定类所有字段,仅仅保留指定字段
* 注意: 该配置优先级高于skipAllIgnore和ConvertColumnEntry配置 * * @param type 指定的类 * @param excludeColumns 需要排除的字段名 */ public final void registerIgnoreAll(final Class type, String... excludeColumns) { Set set = ignoreAlls.get(type); if (set == null) { ignoreAlls.put(type, new HashSet<>(Arrays.asList(excludeColumns))); } else { set.addAll(Arrays.asList(excludeColumns)); } } public final void register(final Class type, boolean ignore, String... columns) { for (String column : columns) { register(type, column, new ConvertColumnEntry(column, ignore)); } } public final boolean register(final Class type, String column, String alias) { return register(type, column, new ConvertColumnEntry(alias)); } public final boolean register(final Class type, String column, ConvertColumnEntry entry) { if (type == null || column == null || entry == null) return false; try { final Field field = type.getDeclaredField(column); String get = "get"; if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is"; char[] cols = column.toCharArray(); cols[0] = Character.toUpperCase(cols[0]); String col2 = new String(cols); try { register(type.getMethod(get + col2), entry); } catch (Exception ex) { } try { register(type.getMethod("set" + col2, field.getType()), entry); } catch (Exception ex) { } return register(field, entry); } catch (Exception e) { return false; } } public final boolean register(final AccessibleObject field, final ConvertColumnEntry entry) { if (field == null || entry == null) return false; this.columnEntrys.put(field, entry); return true; } public final void reloadCoder(final Type type) { this.register(type, this.createDecoder(type)); this.register(type, this.createEncoder(type)); } public final void reloadCoder(final Type type, final Class clazz) { this.register(type, this.createDecoder(type, clazz)); this.register(type, this.createEncoder(type, clazz)); } public final void register(final Class clazz, final Creator creator) { creators.put(clazz, creator); } public final Creator findCreator(Class type) { Creator creator = creators.get(type); if (creator != null) return creator; return this.parent == null ? null : this.parent.findCreator(type); } public final Creator loadCreator(Class type) { Creator result = findCreator(type); if (result == null) { result = Creator.create(type); if (result != null) creators.put(type, result); } return result; } //---------------------------------------------------------------------- public final Encodeable getAnyEncoder() { return (Encodeable) anyEncoder; } public final void register(final Type clazz, final SimpledCoder coder) { decoders.put(clazz, coder); encoders.put(clazz, coder); } public final void register(final Type clazz, final Decodeable decoder, final Encodeable encoder) { decoders.put(clazz, decoder); encoders.put(clazz, encoder); } public final void register(final Type clazz, final Decodeable decoder) { decoders.put(clazz, decoder); } public final void register(final Type clazz, final Encodeable encoder) { encoders.put(clazz, encoder); } //coder = null表示删除该字段的指定SimpledCoder public final void register(final Class clazz, final String field, final SimpledCoder coder) { if (field == null || clazz == null) return; try { clazz.getDeclaredField(field); } catch (Exception e) { throw new RuntimeException(clazz + " not found field(" + field + ")"); } if (coder == null) { Map map = this.fieldCoders.get(clazz); if (map != null) map.remove(field); } else { this.fieldCoders.computeIfAbsent(clazz, c -> new ConcurrentHashMap<>()).put(field, coder); } } public final SimpledCoder findFieldCoder(final Type clazz, final String field) { if (field == null) return null; Map> map = this.fieldCoders.get(clazz); if (map == null) return parent == null ? null : parent.findFieldCoder(clazz, field); return (SimpledCoder) map.get(field); } public final Decodeable findDecoder(final Type type) { Decodeable rs = (Decodeable) decoders.get(type); if (rs != null) return rs; return this.parent == null ? null : this.parent.findDecoder(type); } public final Encodeable findEncoder(final Type type) { Encodeable rs = (Encodeable) encoders.get(type); if (rs != null) return rs; return this.parent == null ? null : this.parent.findEncoder(type); } public final Decodeable loadDecoder(final Type type) { Decodeable decoder = findDecoder(type); if (decoder != null) return decoder; if (type instanceof GenericArrayType) return createArrayDecoder(type); Class clazz; if (type instanceof ParameterizedType) { final ParameterizedType pts = (ParameterizedType) type; clazz = (Class) (pts).getRawType(); } else if (type instanceof TypeVariable) { // e.g. final TypeVariable tv = (TypeVariable) type; Class cz = tv.getBounds().length == 0 ? Object.class : null; for (Type f : tv.getBounds()) { if (f instanceof Class) { cz = (Class) f; break; } } clazz = cz; if (cz == null) throw new ConvertException("not support the type (" + type + ")"); } else if (type instanceof WildcardType) { // e.g. final WildcardType wt = (WildcardType) type; Class cz = null; for (Type f : wt.getUpperBounds()) { if (f instanceof Class) { cz = (Class) f; break; } } clazz = cz; if (cz == null) throw new ConvertException("not support the type (" + type + ")"); } else if (type instanceof Class) { clazz = (Class) type; } else { throw new ConvertException("not support the type (" + type + ")"); } //此处不能再findDecoder,否则type与class不一致, 如: RetResult 和 RetResult return createDecoder(type, clazz); } public final Decodeable createDecoder(final Type type) { Class clazz; if (type instanceof ParameterizedType) { final ParameterizedType pts = (ParameterizedType) type; clazz = (Class) (pts).getRawType(); } else if (type instanceof Class) { clazz = (Class) type; } else { throw new ConvertException("not support the type (" + type + ")"); } return createDecoder(type, clazz); } private Decodeable createDecoder(final Type type, final Class clazz) { Decodeable decoder = null; ObjectDecoder od = null; if (clazz.isEnum()) { decoder = createEnumSimpledCoder(clazz); } else if (clazz.isArray()) { decoder = createArrayDecoder(type); } else if (Collection.class.isAssignableFrom(clazz)) { decoder = createCollectionDecoder(type); } else if (Stream.class.isAssignableFrom(clazz)) { decoder = createStreamDecoder(type); } else if (Map.class.isAssignableFrom(clazz)) { decoder = createMapDecoder(type); } else if (Optional.class == clazz) { decoder = new OptionalCoder(this, type); } else if (clazz == Object.class) { od = createObjectDecoder(type); decoder = od; } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz || clazz.getName().startsWith("java.awt.geom.Point2D")) { Decodeable simpleCoder = null; for (final Method method : clazz.getDeclaredMethods()) { if (!Modifier.isStatic(method.getModifiers())) continue; Class[] paramTypes = method.getParameterTypes(); if (paramTypes.length != 1) continue; if (paramTypes[0] != ConvertFactory.class && paramTypes[0] != this.getClass()) continue; if (!Decodeable.class.isAssignableFrom(method.getReturnType())) continue; try { method.setAccessible(true); simpleCoder = (Decodeable) method.invoke(null, this); break; } catch (Exception e) { } } if (simpleCoder == null) { od = createObjectDecoder(type); decoder = od; } else { decoder = simpleCoder; } } if (decoder == null) throw new ConvertException("not support the type (" + type + ")"); register(type, decoder); if (od != null) od.init(this); return decoder; } public final Encodeable loadEncoder(final Type type) { Encodeable encoder = findEncoder(type); if (encoder != null) return encoder; if (type instanceof GenericArrayType) return createArrayEncoder(type); Class clazz; if (type instanceof ParameterizedType) { final ParameterizedType pts = (ParameterizedType) type; clazz = (Class) (pts).getRawType(); } else if (type instanceof TypeVariable) { TypeVariable tv = (TypeVariable) type; Type t = Object.class; if (tv.getBounds().length == 1) { t = tv.getBounds()[0]; } if (!(t instanceof Class)) t = Object.class; clazz = (Class) t; } else if (type instanceof Class) { clazz = (Class) type; } else { throw new ConvertException("not support the type (" + type + ")"); } //此处不能再findEncoder,否则type与class不一致, 如: RetResult 和 RetResult return createEncoder(type, clazz); } public final Encodeable createEncoder(final Type type) { Class clazz; if (type instanceof ParameterizedType) { final ParameterizedType pts = (ParameterizedType) type; clazz = (Class) (pts).getRawType(); } else if (type instanceof Class) { clazz = (Class) type; } else { throw new ConvertException("not support the type (" + type + ")"); } return createEncoder(type, clazz); } private Encodeable createEncoder(final Type type, final Class clazz) { Encodeable encoder = null; ObjectEncoder oe = null; if (clazz.isEnum()) { encoder = createEnumSimpledCoder(clazz); } else if (clazz.isArray()) { encoder = createArrayEncoder(type); } else if (Collection.class.isAssignableFrom(clazz)) { encoder = createCollectionEncoder(type); } else if (Stream.class.isAssignableFrom(clazz)) { encoder = createStreamEncoder(type); } else if (Map.class.isAssignableFrom(clazz)) { encoder = createMapEncoder(type); } else if (Optional.class == clazz) { encoder = new OptionalCoder(this, type); } else if (clazz == Object.class) { return (Encodeable) this.anyEncoder; } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) { Encodeable simpleCoder = null; for (final Method method : clazz.getDeclaredMethods()) { if (!Modifier.isStatic(method.getModifiers())) continue; Class[] paramTypes = method.getParameterTypes(); if (paramTypes.length != 1) continue; if (paramTypes[0] != ConvertFactory.class && paramTypes[0] != this.getClass()) continue; if (!Encodeable.class.isAssignableFrom(method.getReturnType())) continue; try { method.setAccessible(true); simpleCoder = (Encodeable) method.invoke(null, this); break; } catch (Exception e) { } } if (simpleCoder == null) { oe = createObjectEncoder(type); encoder = oe; } else { encoder = simpleCoder; } } if (encoder == null) throw new ConvertException("not support the type (" + type + ")"); register(type, encoder); if (oe != null) oe.init(this); return encoder; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy