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

com.github.fieldintercept.KeyValueFieldIntercept Maven / Gradle / Ivy

The newest version!
package com.github.fieldintercept;

import com.github.fieldintercept.util.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * key value 字段字段设置名称
 *
 * @author acer01
 */
public class KeyValueFieldIntercept implements ReturnFieldDispatchAop.FieldIntercept, ReturnFieldDispatchAop.SelectMethodHolder {
    protected final Class keyClass;
    protected final Class valueClass;
    protected final Function, Map> selectValueMapByKeys;
    protected Object configurableEnvironment;

    public KeyValueFieldIntercept() {
        this(null, null);
    }

    public KeyValueFieldIntercept(Class keyClass) {
        this(keyClass, null);
    }

    public KeyValueFieldIntercept(Class keyClass, Class valueClass) {
        this(keyClass, valueClass, null);
    }

    public KeyValueFieldIntercept(Class keyClass, Class valueClass, Function, Map> selectValueMapByKeys) {
        if (keyClass == null) {
            if (getClass() != KeyValueFieldIntercept.class) {
                try {
                    Class key = TypeUtil.findGenericType(this, KeyValueFieldIntercept.class, "KEY");
                    keyClass = (Class) key;
                } catch (IllegalStateException ignored) {
                }
            }
            if (keyClass == null) {
                keyClass = (Class) Integer.class;
            }
        }
        if (valueClass == null) {
            try {
                valueClass = (Class) TypeUtil.findGenericType(this, KeyValueFieldIntercept.class, "VALUE");
            } catch (Exception e) {
                valueClass = (Class) Object.class;
            }
        }
        this.keyClass = keyClass;
        this.valueClass = valueClass;
        this.selectValueMapByKeys = selectValueMapByKeys;
    }

    private static String cacheKey(Object key) {
        return String.valueOf(key);
    }

    public Class getValueClass() {
        return valueClass;
    }

    public Class getKeyClass() {
        return keyClass;
    }

    public Function, Map> getSelectValueMapByKeys() {
        return selectValueMapByKeys;
    }

    @Override
    public final void accept(JOIN_POINT joinPoint, List cFields) {
        Set keyDataList = getKeyDataByFields(cFields);
        if (keyDataList == null || keyDataList.isEmpty()) {
            return;
        }
        Map currentLocalCache = ReturnFieldDispatchAop.getLocalCache(cFields, this);
        Map valueMap = cacheSelectValueMapByKeys(currentLocalCache, cFields, keyDataList);

        SnapshotCompletableFuture> future = ReturnFieldDispatchAop.getAsync(cFields, this);
        if (future != null) {
            future.addBeforeCompleteListener((result, throwable) -> {
                if (result != null && !result.isEmpty()) {
                    valueMap.putAll(result);
                    putCache(currentLocalCache, result);
                }
                if (!valueMap.isEmpty()) {
                    Map attachment = PlatformDependentUtil.removeAttachment(valueMap);
                    setProperty(cFields, valueMap, attachment);
                }
            });
        } else if (!valueMap.isEmpty()) {
            Map attachment = PlatformDependentUtil.removeAttachment(valueMap);
            setProperty(cFields, valueMap, attachment);
        }
    }

    private Map cacheSelectValueMapByKeys(Map currentLocalCache, List cFields, Set keys) {
        // 从缓存中加载
        Map valueMap = loadCache(currentLocalCache, keys);
        // 全部命中
        if (valueMap.size() == keys.size()) {
            return valueMap;
        }

        // 未命中的查库
        Set remainingCacheMissKeys;
        if (valueMap.isEmpty()) {
            remainingCacheMissKeys = keys;
        } else {
            remainingCacheMissKeys = new LinkedHashSet<>(keys);
            remainingCacheMissKeys.removeAll(valueMap.keySet());
        }

        // 查库与缓存数据合并
        Map loadValueMap = selectValueMapByKeys(cFields, remainingCacheMissKeys);
        if (loadValueMap != null) {
            valueMap.putAll(loadValueMap);

            // 放入缓存
            putCache(currentLocalCache, loadValueMap);
        }
        return valueMap;
    }

    private Map loadCache(Map currentLocalCache, Set keys) {
        Map valueMap = new LinkedHashMap<>((int) (keys.size() / 0.75F + 1));
        if (currentLocalCache != null && !currentLocalCache.isEmpty()) {
            for (KEY key : keys) {
                String stringKey = cacheKey(key);
                if (currentLocalCache.containsKey(stringKey)) {
                    valueMap.put(key, currentLocalCache.get(stringKey));
                }
            }
        }
        return valueMap;
    }

    private void putCache(Map currentLocalCache, Map valueMap) {
        // 放入缓存
        if (currentLocalCache != null) {
            for (Map.Entry entry : valueMap.entrySet()) {
                currentLocalCache.put(cacheKey(entry.getKey()), entry.getValue());
            }
        }
    }

    /**
     * 查询名称by keys
     *
     * @param keys 多个key
     * @return key 与名称的映射
     */
    public Map selectValueMapByKeys(Collection keys) {
        return null;
    }

    public Map selectSerializeValueMapByKeys(List serializeCFields, Collection keys) {
        Map valueMap = selectValueMapByKeys(CField.parse(serializeCFields), keys);
        Map attachment = newtSerializeAttachment(serializeCFields, valueMap);
        return PlatformDependentUtil.mergeAttachment(valueMap, attachment);
    }

    protected Map newtSerializeAttachment(List serializeCFields, Map valueMap) {
        return null;
    }

    public Map selectValueMapByKeys(List cFields, Collection keys) {
        Map valueMap = selectValueMapByKeys(keys);
        if (valueMap == null) {
            if (selectValueMapByKeys == null) {
                throw new UnsupportedOperationException("您的selectValueMapByKeys方法未实现完全");
            }
            valueMap = selectValueMapByKeys.apply(keys);
        }
        return valueMap;
    }

    protected KEY[] rewriteKeyDataIfNeed(KEY keyData, CField cField, Map valueMap, Map attachment) {
        Object[] attachmentValue;
        if (attachment != null && !attachment.isEmpty() && (attachmentValue = TypeUtil.cast(attachment.get(cField.keyDataId(keyData)), Object[].class)) != null) {
            return (KEY[]) attachmentValue;
        } else {
            KEY[] arr = (KEY[]) Array.newInstance(keyData.getClass(), 1);
            arr[0] = keyData;
            return arr;
        }
    }

    protected Set getKeyDataByFields(List cFields) {
        Set totalKeyDataList = new LinkedHashSet<>();
        for (CField cField : cFields) {
            String[] keyFieldNames = getKeyFieldName(cField.getAnnotation());
            Object keyData = getKeyDataByField(cField.getBeanHandler(), keyFieldNames);
            Collection keyDataList = splitKeyData(keyData);
            if (keyDataList != null) {
                totalKeyDataList.addAll(keyDataList);
                cField.setKeyDataList(keyDataList);
            }
        }
        return totalKeyDataList;
    }

    protected String[] getKeyFieldName(Annotation annotation) {
        Object keyField = AnnotationUtil.getValue(annotation, "keyField");
        if (keyField instanceof String[]) {
            return (String[]) keyField;
        } else if (keyField instanceof String) {
            return new String[]{(String) keyField};
        } else {
            return null;
        }
    }

    protected boolean isNull(Object value) {
        return value == null || "".equals(value) || "null".equals(value);
    }

    protected Object getKeyDataByField(BeanMap beanHandler, String[] keyFieldNames) {
        if (keyFieldNames != null) {
            for (String keyFieldName : keyFieldNames) {
                Object keyData = beanHandler.get(keyFieldName);
                if (!isNull(keyData)) {
                    return keyData;
                }
            }
        }
        return null;
    }

    protected Collection splitKeyData(Object keyData) {
        Collection keyDataList = null;
        if (isNull(keyData)) {
            return null;
        } else if (keyData.getClass().isArray()) {
            int length = Array.getLength(keyData);
            for (int i = 0; i < length; i++) {
                Object e = Array.get(keyData, i);
                if (isNull(e)) {
                    continue;
                }
                KEY key = cast(e, keyClass);
                if (key != null) {
                    if (keyDataList == null) {
                        keyDataList = new ArrayList<>();
                    }
                    keyDataList.add(key);
                }
            }
        } else if (keyData instanceof Iterable) {
            for (Object e : (Iterable) keyData) {
                if (isNull(e)) {
                    continue;
                }
                KEY key = cast(e, keyClass);
                if (key != null) {
                    if (keyDataList == null) {
                        keyDataList = new ArrayList<>();
                    }
                    keyDataList.add(key);
                }
            }
        } else if (keyData instanceof CharSequence) {
            for (String e : keyData.toString().split(",")) {
                if (isNull(e)) {
                    continue;
                }
                KEY key = cast(e, keyClass);
                if (key != null) {
                    if (keyDataList == null) {
                        keyDataList = new ArrayList<>();
                    }
                    keyDataList.add(key);
                }
            }
        } else {
            try {
                KEY key = cast(keyData, keyClass);
                if (key != null) {
                    keyDataList = Collections.singletonList(key);
                }
            } catch (Exception e) {
                //skip
            }
        }
        return keyDataList;
    }

    protected  void addList(CField cField, Object value, Class genericType, Consumer list) {
        if (value == null) {
            return;
        }
        if (value instanceof Collection && !Collection.class.isAssignableFrom(genericType)) {
            for (Object o : (Collection) value) {
                addList(cField, o, genericType, list);
            }
        } else {
            String resolveValue = cField.resolvePlaceholders(value);
            if (resolveValue != null) {
                value = resolveValue;
            }
            if (cField.getType() != String.class && value instanceof String && ((String) value).contains(",")) {
                for (String s : ((String) value).split(",")) {
                    list.accept(cast(s, genericType));
                }
            } else {
                list.accept(cast(value, genericType));
            }
        }
    }

    protected void setProperty(List cFieldList, Map valueMap, Map attachment) {
        Map stringKeyMap = null;
        for (CField cField : cFieldList) {
            Class genericType = cField.getGenericType();
            Class fieldType = cField.getField().getType();
            Collection keyDataList = cField.getKeyDataList();
            VALUE value = null;
            StringJoiner joiner = null;
            if (keyDataList == null || keyDataList.isEmpty()) {
                if (List.class.isAssignableFrom(fieldType)) {
                    value = (VALUE) new ArrayList();
                } else if (Set.class.isAssignableFrom(fieldType)) {
                    value = (VALUE) new LinkedHashSet(1);
                } else if (fieldType.isArray()) {
                    value = (VALUE) Array.newInstance(genericType, 0);
                }
            } else if (keyDataList.size() == 1) {
                KEY[] rewriteKeyDataList = rewriteKeyDataIfNeed(keyDataList.iterator().next(), cField, valueMap, attachment);
                setKeyData(cField, rewriteKeyDataList);
                value = choseValue(valueMap, rewriteKeyDataList);
                if (value == null && rewriteKeyDataList != null && rewriteKeyDataList.length > 0) {
                    if (stringKeyMap == null) {
                        stringKeyMap = toStringKeyMap(valueMap);
                    }
                    value = choseValue((Map) stringKeyMap, (KEY[]) toStringKey(rewriteKeyDataList));
                }
                if (List.class.isAssignableFrom(fieldType)) {
                    Collection list = new ArrayList<>(1);
                    addList(cField, value, genericType, list::add);
                    value = (VALUE) list;
                } else if (Set.class.isAssignableFrom(fieldType)) {
                    Collection list = new LinkedHashSet<>(1);
                    addList(cField, value, genericType, list::add);
                    value = (VALUE) list;
                } else if (fieldType.isArray()) {
                    Object array = Array.newInstance(genericType, 1);
                    String resolveValue = cField.resolvePlaceholders(value);
                    if (resolveValue != null) {
                        value = (VALUE) cast(resolveValue, genericType);
                    }
                    Array.set(array, 0, value);
                    value = (VALUE) array;
                }
            } else {
                List list = null;
                Set set = null;
                Object array = null;
                if (List.class.isAssignableFrom(fieldType)) {
                    list = new ArrayList<>(10);
                    value = (VALUE) list;
                } else if (Set.class.isAssignableFrom(fieldType)) {
                    set = new LinkedHashSet<>(10);
                    value = (VALUE) set;
                } else if (fieldType.isArray()) {
                    array = Array.newInstance(genericType, keyDataList.size());
                    value = (VALUE) array;
                } else if (fieldType == String.class) {
                    String joinDelimiter = getAnnotationJoinDelimiter(cField.getAnnotation());
                    joiner = new StringJoiner(joinDelimiter);
                }
                int i = 0;
                for (KEY keyData : keyDataList) {
                    i++;
                    KEY[] rewriteKeyDataList = rewriteKeyDataIfNeed(keyData, cField, valueMap, attachment);
                    setKeyData(cField, rewriteKeyDataList);
                    VALUE eachValue = choseValue(valueMap, rewriteKeyDataList);
                    if (eachValue == null && rewriteKeyDataList != null && rewriteKeyDataList.length > 0) {
                        if (stringKeyMap == null) {
                            stringKeyMap = toStringKeyMap(valueMap);
                        }
                        eachValue = choseValue((Map) stringKeyMap, (KEY[]) toStringKey(rewriteKeyDataList));
                    }
                    if (eachValue == null) {
                        continue;
                    }
                    if (list != null) {
                        addList(cField, eachValue, genericType, list::add);
                    } else if (set != null) {
                        addList(cField, eachValue, genericType, set::add);
                    } else if (array != null) {
                        String resolveValue = cField.resolvePlaceholders(eachValue);
                        if (resolveValue != null) {
                            eachValue = (VALUE) cast(resolveValue, genericType);
                        }
                        Array.set(array, i, eachValue);
                    } else if (joiner != null && !isNull(eachValue)) {
                        addList(cField, eachValue, String.class, joiner::add);
                    } else {
                        value = eachValue;
                        break;
                    }
                }
            }

            if (joiner != null && joiner.length() > 0) {
                value = (VALUE) joiner.toString();
            }
            if (value != null) {
                if (fieldType.isEnum() && value.getClass().isEnum()) {
                    cField.setValue(value);
                } else if (cField.existPlaceholder()) {
                    String resolveValue = cField.resolvePlaceholders(value);
                    if (resolveValue != null) {
                        cField.setValue(resolveValue);
                    }
                } else {
                    cField.setValue(value);
                }
            }
        }
    }

    private void setKeyData(CField cField, KEY[] rewriteKeyDataList) {
        if (rewriteKeyDataList == null) {
            return;
        }
        Object keyData;
        if (rewriteKeyDataList.length == 1) {
            keyData = rewriteKeyDataList[0];
        } else if (rewriteKeyDataList.length == 0) {
            keyData = null;
        } else {
            keyData = new ArrayList<>(Arrays.asList(rewriteKeyDataList));
        }
        cField.setKeyData(keyData);
    }

    protected  TYPE cast(Object object, Class type) {
        if (Enum.class.isAssignableFrom(type)) {
            if (type.isEnum()) {
                return (TYPE) castEnum(object, (Class) type);
            } else {
                throw new IllegalStateException("cast need " + type + " extends java.lang.Enum");
            }
        }
        return TypeUtil.castIfBeanCast(object, type);
    }

    protected  TYPE castEnum(Object object, Class type) {
        Collection enumSet = (Collection) EnumSet.allOf((Class) type);
        if (enumSet.isEmpty()) {
            return null;
        }
        Class keyClass = enumSet.stream()
                .map(Enum::getKey)
                .filter(Objects::nonNull)
                .findFirst()
                .map(Object::getClass)
                .orElse(null);
        Object keyCast;
        if (keyClass == null) {
            keyCast = null;
        } else {
            keyCast = TypeUtil.castIfBeanCast(object, keyClass);
        }
        for (Enum o : enumSet) {
            Object key = o.getKey();
            if (Objects.equals(key, keyCast)) {
                return (TYPE) o;
            }
        }
        return null;
    }

    protected VALUE choseValue(Map valueMap, KEY[] keyDataList) {
        if (keyDataList == null) {
            return null;
        }
        for (KEY keyData : keyDataList) {
            VALUE value = valueMap.get(keyData);
            if (value != null) {
                return value;
            }
        }
        return null;
    }

    protected String getAnnotationJoinDelimiter(Annotation annotation) {
        Object joinDelimiter = AnnotationUtil.getValue(annotation, "joinDelimiter");
        if (joinDelimiter == null) {
            return ",";
        } else {
            return joinDelimiter.toString();
        }
    }

    public void setConfigurableEnvironment(Object configurableEnvironment) {
        this.configurableEnvironment = configurableEnvironment;
    }

    private Map toStringKeyMap(Map nameMap) {
        Map result = new HashMap<>();
        for (Map.Entry entry : nameMap.entrySet()) {
            result.put(Objects.toString(entry.getKey(), null), entry.getValue());
        }
        return result;
    }

    private String[] toStringKey(KEY[] rewriteKeyDataList) {
        String[] strings = new String[rewriteKeyDataList.length];
        for (int i = 0; i < rewriteKeyDataList.length; i++) {
            strings[i] = Objects.toString(rewriteKeyDataList[i], null);
        }
        return strings;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy