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

com.moon.mapping.processing.MapFieldFactory Maven / Gradle / Ivy

package com.moon.mapping.processing;

import com.moon.mapping.annotation.MapProperty;
import org.joda.time.*;

import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

import static com.moon.mapping.processing.DetectUtils.isTypeof;
import static com.moon.mapping.processing.DetectUtils.isTypeofAny;
import static com.moon.mapping.processing.ElementUtils.getSimpleName;
import static com.moon.mapping.processing.StringUtils.*;

/**
 * @author benshaoye
 */
final class MapFieldFactory {

    private final static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private final static String DOUBLE = "double";
    private final static String LONG = "long";
    private final static String INT = "int";

    private final static Map dateFormats = new HashMap<>();

    private boolean warned = false;

    public MapFieldFactory() {
        dateFormats.put(java.time.LocalDate.class.getName(), "yyyy-MM-dd");
        dateFormats.put(java.time.LocalTime.class.getName(), "HH:mm:ss");
        dateFormats.put(java.time.YearMonth.class.getName(), "yyyy-MM");
        dateFormats.put(java.time.Year.class.getName(), "yyyy");
        dateFormats.put(java.time.MonthDay.class.getName(), "MM-dd");
        if (Imported.JODA_TIME) {
            dateFormats.put(MonthDay.class.getName(), "MM-dd");
            dateFormats.put(YearMonth.class.getName(), "yyyy-MM");
            dateFormats.put(LocalTime.class.getName(), "HH:mm:ss");
            dateFormats.put(LocalDate.class.getName(), "yyyy-MM-dd");
        }
    }

    public String doConvertField(
        final Manager manager
    ) {
        MappingModel model = manager.getModel();
        unWarned();
        String field;
        if (!model.isGetterGeneric() && !model.isSetterGeneric()) {
            field = doConvertDeclaredField(manager);
            if (field == null && isSubtypeOf(model.getGetterDeclareType(), model.getSetterDeclareType())) {
                field = "{toName}.{setterName}({fromName}.{getterName}());";
            }
            if (field == null && !isWarned()) {
                field = warningAndIgnored(model);
            }
        } else if (model.isGetterGeneric() && model.isSetterGeneric()) {
            final String setterTypeString = model.getSetterActualType();
            final String getterTypeString = model.getGetterActualType();
            field = doConvertGenerify(manager, getterTypeString, setterTypeString);
        } else if (model.isGetterGeneric()) {
            final String setterTypeString = model.getSetterDeclareType();
            final String getterTypeString = model.getGetterActualType();
            field = doConvertGenerify(manager, getterTypeString, setterTypeString);
        } else if (model.isSetterGeneric()) {
            final String setterTypeString = model.getSetterActualType();
            final String getterTypeString = model.getGetterDeclareType();
            field = doConvertGenerify(manager, getterTypeString, setterTypeString);
        } else {
            throw new IllegalStateException("This is impossible.");
        }
        return onDeclareCompleted(field, model);
    }

    private String doConvertGenerify(
        Manager manager, String getterTypeString, String setterTypeString
    ) {
        MappingModel model = manager.getModel();
        Elements utils = EnvUtils.getUtils();
        TypeMirror setterType = utils.getTypeElement(setterTypeString).asType();
        TypeMirror getterType = utils.getTypeElement(getterTypeString).asType();
        if (EnvUtils.getTypes().isSubtype(getterType, setterType)) {
            String field = "{toName}.{setterName}(({setterType}){fromName}.{getterName}());";
            return Replacer.setterType.replace(field, manager.onImported(setterTypeString));
        } else {
            return warningAndIgnored(model);
        }
    }

    @SuppressWarnings("all")
    private String doConvertDeclaredField(
        final Manager manager
    ) {
        MappingModel model = manager.getModel();
        String t0 = declareOnDefault(model, manager);
        if (t0 == null) {
            t0 = declare2String(model, manager);
        }
        if (t0 == null) {
            t0 = declare2PrimitiveNumber(model, manager);
        }
        if (t0 == null) {
            t0 = declare2WrappedNumber(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Enum(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Boolean(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Char(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Date(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Calendar(model, manager);
        }
        if (t0 == null) {
            t0 = declare2Jdk8Time(model, manager);
        }
        if (t0 == null) {
            t0 = declare2JodaTime(model, manager);
        }
        if (t0 == null) {
            t0 = declare2BigInteger(model, manager);
        }
        if (t0 == null) {
            t0 = declare2BigDecimal(model, manager);
        }
        return onDeclareCompleted(t0, model);
    }

    private String declareOnDefault(MappingModel model, Manager manager) {
        /** 只有在没有注解{@link MapProperty}时,即没有默认值、没有格式化、没有忽略、没有重命名 */
        if (model.nonAnnotatedMapProperty()) {
            final String setterDeclareType = model.getSetterDeclareType();
            final String getterDeclareType = model.getGetterDeclareType();
            if (Objects.equals(setterDeclareType, getterDeclareType)//
                || isSubtypeOf(getterDeclareType, setterDeclareType)) {
                return manager.ofConvert().onSameType();
            }
        }
        return null;
    }

    /**
     * 已支持:枚举默认值、枚举到字符串数字等默认类型转换、指定属性名
     * 

* 不支持格式化 * * @param model * @param manager * * @return */ private String declare2Enum(MappingModel model, Manager manager) { final String setterDeclareType = model.getSetterDeclareType(); if (!isEnum(setterDeclareType)) { return null; } String t0; final MappingManager mapping = manager.getMapping(); final String getterDeclareType = model.getGetterDeclareType(); final String dftValue = manager.staticVarForDefaultEnumOnDeclare(); if (Objects.equals(getterDeclareType, setterDeclareType)) { return mapping.onDeclare(null, dftValue); } if (isString(getterDeclareType)) { return mapping.onDeclare("{setterType}.valueOf({var})", dftValue); } if (isPrimitiveNumber(getterDeclareType)) { String enumValues = manager.staticVarForEnumValuesOnDeclare(); t0 = Replacer.name.replace("{name}[{cast}{var}]", enumValues); t0 = Replacer.cast.replace(t0, castPrimitiveIfGtTop(getterDeclareType, INT)); return mapping.onDeclare(t0, dftValue); } if (isSubtypeOf(getterDeclareType, Number.class)) { String enumValues = manager.staticVarForEnumValuesOnDeclare(); t0 = Replacer.name.replace("{name}[{var}.intValue()]", enumValues); return mapping.onDeclare(t0, dftValue); } return warningAndIgnored(model); } /** * 所有数据类型到字符串的转换 * 1. 基本数字类型:String.valueOf(..) + 格式化 * 2. 数字包装类 + 格式化 * 3. 枚举 * 4. jdk8 日期类型 + 格式化 * 5. Date、Calendar、sql.Date 日期类型 + 格式化 * 6. Joda 日期类型格式化 * 7. 其他对象到直接调用 Object.toString() * * @param model * @param manager * * @return */ private String declare2String(final MappingModel model, Manager manager) { final String setterDeclareType = model.getSetterDeclareType(); if (!isString(setterDeclareType)) { return null; } String t0 = null; final MappingManager mapping = manager.getMapping(); final PropertyAttr attr = model.getAttr(); final ConvertManager convert = manager.ofConvert(); final String getterDeclareType = model.getGetterDeclareType(); final String formatVal = attr.formatValue(); final String dftValue = manager.staticVarForDefaultString(); if (isString(getterDeclareType)) { return mapping.onDeclare(null, dftValue); } else if (StringUtils.isPrimitiveNumber(getterDeclareType)) { // getter 是基本数据类型,没有默认值,因为 get 不到 null if (formatVal == null) { t0 = mapping.onDeclare("{setterType}.valueOf({var})", null); } else { String stringType = String.class.getCanonicalName(); String targetType = isCompatible(LONG, getterDeclareType) ? LONG : DOUBLE; CallerInfo info = convert.find(stringType, targetType, stringType); String mapper = info.toString("{fromName}.{getterName}()", strWrapped(formatVal)); t0 = mapping.onDeclare(mapper, null); } } else if (StringUtils.isPrimitive(getterDeclareType)) { t0 = mapping.onDeclare("{setterType}.valueOf({var})", null); } else if (isEnum(getterDeclareType)) { t0 = mapping.onDeclare("{var}.name()", dftValue); } else if (isFormattable(formatVal, getterDeclareType, Number.class)) { CallerInfo mapper = convert.find(String.class, Number.class, String.class); t0 = mapping.onDeclare(mapper.toString(null, strWrapped(formatVal)), dftValue); } if (t0 == null) { final String dateFormat = defaultDatePattern(getterDeclareType, formatVal); if (isFormattable(dateFormat, getterDeclareType, Date.class)) { CallerInfo mapper = convert.find(String.class, Calendar.class, String.class); t0 = mapping.onDeclare(mapper.toString(null, strWrapped(formatVal)), dftValue); } else if (isFormattable(dateFormat, getterDeclareType, Calendar.class)) { CallerInfo mapper = convert.find(String.class, Calendar.class, String.class); t0 = mapping.onDeclare(mapper.toString(null, strWrapped(formatVal)), dftValue); } else if (isFormattable(dateFormat, getterDeclareType, TemporalAccessor.class)) { String format = manager.staticVarForDateTimeFormatter(dateFormat); String fmt = Replacer.format.replace("{format}.format({var})", format); t0 = mapping.onDeclare(fmt, dftValue); } else if (isJodaFormattable(dateFormat, getterDeclareType)) { String format = manager.staticVarForJodaDateTimeFormatter(dateFormat); String fmt = Replacer.format.replace("{format}.print({var})", format); t0 = mapping.onDeclare(fmt, dftValue); } } if (t0 == null) { t0 = mapping.onDeclare("{var}.toString()", dftValue); } return t0; } private static String useConvertAndDftValAndFormat( MappingModel model, Manager manager, String dftValue, Class getterSuper ) { return useConvertAndDftValAndFormat(// model.getAttr().formatValue(),// model.getSetterDeclareType(),// manager, dftValue, getterSuper); } private static String useConvertAndDftValAndFormat( String format, String setterType, Manager manager, String dftValue, Class getterSuper ) { return manager.ofConvert().useConvert(dftValue, info -> { return info.toString(null, strWrapped(format)); }, setterType, getterSuper, String.class); } /** * 支持的数据转换: * 1. 基本数据类型之间的数据转换 * 2. 包装类到基本数据之间的数据转换 + 默认值 * 3,字符串到基本数据之间的转换 + 格式化 + 默认值 * 4. Number 到基本数据之间的转换 + 默认值 * 5. char 到数字之间的转换(不包括{@link Character}) * 6. 枚举到数字之间的转换,{@link Enum#ordinal()} + 默认值 * 7. util Date 到 long/double 的转换 + 默认值 * 8. jdk8 日期到 long/double 的转换 + 默认值 * 9. joda 日期到 long/double 的转换 + 默认值 * * @param model * @param manager * * @return */ private String declare2PrimitiveNumber(final MappingModel model, Manager manager) { String t0; final MappingManager mapping = manager.getMapping(); final ConvertManager convert = manager.ofConvert(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (!isPrimitiveNumber(setterDeclareType)) { return null; } if (isPrimitiveNumber(getterDeclareType)) { String cast = castPrimitiveIfGtTop(getterDeclareType, setterDeclareType); String template = Replacer.cast.replace("{cast}{var}", cast); return mapping.onDeclare(template, null); } if (StringUtils.isPrimitiveChar(getterDeclareType)) { String cast = castPrimitiveIfLtLow(setterDeclareType, INT); String mapper = Replacer.cast.replace("{cast}{var}", cast); return mapping.onDeclare(mapper, null); } final String dftValue = manager.staticVarForDefaultNumberOnDeclare(); if (isSubtypeOf(getterDeclareType, Number.class)) { return mapping.onDeclare("{var}.{setterType}Value()", dftValue); } if (isString(getterDeclareType)) { String format = model.getAttr().formatValue(); String setterWrapped = StringUtils.toWrappedType(manager.onImported(setterDeclareType)); if (isNullString(format)) { String name = INT.equals(setterDeclareType) ? "Int" : getSimpleName(setterWrapped); String mapper = Replacer.name.replace("{setterType}.parse{name}({var})", name); mapper = Replacer.setterType.replace(mapper, manager.onImported(setterWrapped)); return mapping.onDeclare(mapper, dftValue); } else { CallerInfo info = convert.find(Number.class, String.class, String.class); String suffix = Replacer.type0.replace(".{type0}Value()", setterDeclareType); String mapper = info.toString(null, strWrapped(format)) + suffix; return mapping.onDeclare(mapper, dftValue); } } if (isEnum(getterDeclareType)) { String cast = castPrimitiveIfLtLow(setterDeclareType, INT); t0 = Replacer.cast.replace("{cast}{var}.ordinal()", cast); return mapping.onDeclare(t0, dftValue); } if (LONG.equals(setterDeclareType)) { if (isSubtypeOf(getterDeclareType, Date.class)) { return mapping.onDeclare("{var}.getTime()", dftValue); } else if (isSubtypeOf(getterDeclareType, Calendar.class)) { return mapping.onDeclare("{var}.getTimeInMillis()", dftValue); } else if (isTypeofAny(getterDeclareType, java.time.LocalDate.class, java.time.LocalDateTime.class, ZonedDateTime.class, OffsetDateTime.class, java.time.Instant.class)) { CallerInfo info = convert.find(setterDeclareType, getterDeclareType); return mapping.onDeclare(info.toString(), dftValue); } else if (Imported.JODA_TIME) { if (isSubtypeOf(getterDeclareType, ReadableInstant.class)) { return mapping.onDeclare("{var}.getMillis()", dftValue); } else if (isTypeofAny(getterDeclareType, LocalDateTime.class, LocalDate.class)) { convert.convertOrWarnedThenNull(dftValue, LONG, getterDeclareType); CallerInfo info = convert.find(LONG, getterDeclareType); if (info != null) { return mapping.onDeclare(info.toString(), dftValue); } } } } return warningAndIgnored(model); } /** * 支持的数据转换: * 1. 基本数据类型之间的数据转换 * 2. 包装类到基本数据之间的数据转换 + 默认值 * 3,字符串到基本数据之间的转换 + 格式化 + 默认值 * 4. Number 到基本数据之间的转换 + 默认值 * 5. char 到数字之间的转换(不包括{@link Character}) * 6. 枚举到数字之间的转换,{@link Enum#ordinal()} + 默认值 * 7. util Date 到 long/double 的转换 + 默认值 * 8. jdk8 日期到 long/double 的转换 + 默认值 * 9. joda 日期到 long/double 的转换 + 默认值 * * @param model * @param manager * * @return */ private String declare2WrappedNumber(final MappingModel model, Manager manager) { String t0; final PropertyAttr attr = model.getAttr(); final MappingManager mapping = manager.getMapping(); final ConvertManager convert = manager.ofConvert(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (isWrappedNumber(setterDeclareType)) { final String setterPrimitive = toPrimitiveType(setterDeclareType); if (isPrimitiveNumber(getterDeclareType)) { String cast = getterDeclareType.equals(setterPrimitive) ? "" : bracketed(setterPrimitive); return mapping.onDeclare(Replacer.cast.replace("{cast}{var}", cast), null); } if (StringUtils.isPrimitiveChar(getterDeclareType)) { String mapper = Replacer.cast.replace("{cast}{var}", bracketed(setterPrimitive)); return mapping.onDeclare(mapper, null); } final String dftValue = manager.staticVarForDefaultNumberOnDeclare(); if (isWrappedNumber(getterDeclareType)) { if (Objects.equals(setterDeclareType, getterDeclareType)) { t0 = mapping.onDeclare(null, dftValue); } else { String tx = Replacer.type0.replace("{var}.{type0}Value()", setterPrimitive); t0 = mapping.onDeclare(tx, dftValue); } } else if (isString(getterDeclareType)) { if (attr.formatValue() == null) { String name = INT.equals(setterPrimitive) ? "Int" : getSimpleName(setterDeclareType); String mapper = Replacer.name.replace("{setterType}.parse{name}({var})", name); t0 = mapping.onDeclare(mapper, dftValue); } else { CallerInfo info = convert.find(setterDeclareType, String.class, String.class); String mapper = info.toString(null, strWrapped(attr.formatValue())); t0 = mapping.onDeclare(mapper, dftValue); } } else if (isEnum(getterDeclareType)) { String cast = castPrimitiveIfLtLow(setterPrimitive, INT); t0 = Replacer.cast.replace("{setterType}.valueOf({cast}{var}.ordinal())", cast); t0 = mapping.onDeclare(t0, dftValue); } else if (isTypeof(getterDeclareType, Character.class)) { String cast = castPrimitiveIfLtLow(setterPrimitive, INT); String charVal = Replacer.cast.replace("{setterType}.valueOf({cast}{var}.charValue())", cast); t0 = mapping.onDeclare(charVal, dftValue); } else if (isSubtypeOf(getterDeclareType, Number.class)) { String mapper = Replacer.type0.replace("{var}.{type0}Value()", setterPrimitive); t0 = mapping.onDeclare(mapper, dftValue); } else if (Long.class.getCanonicalName().equals(setterDeclareType)) { if (isSubtypeOf(getterDeclareType, Date.class)) { t0 = mapping.onDeclare("{var}.getTime()", dftValue); } else if (isSubtypeOf(getterDeclareType, Calendar.class)) { t0 = mapping.onDeclare("{var}.getTimeInMillis()", dftValue); } else if (Imported.JODA_TIME) { if (isSubtypeOf(getterDeclareType, ReadableInstant.class)) { t0 = mapping.onDeclare("{var}.getMillis()", dftValue); } else if (isTypeofAny(getterDeclareType, LocalDateTime.class, LocalDate.class, MutableDateTime.class)) { t0 = mapping.onDeclare("{var}.toDate().getTime()", dftValue); } else { t0 = warningAndIgnored(model); } } else { t0 = warningAndIgnored(model); } } else { t0 = warningAndIgnored(model); } } else if (isTypeof(setterDeclareType, Number.class)) { if (isPrimitiveNumber(getterDeclareType)) { return mapping.onDeclare("{var}", null); } else if (isPrimitiveChar(getterDeclareType)) { return mapping.onDeclare("(int){var}", null); } final String dftValue = manager.staticVarForDefaultNumber(INT); if (isSubtypeOf(getterDeclareType, Number.class)) { return mapping.onDeclare("{var}", dftValue); } else if (isEnum(getterDeclareType)) { return mapping.onDeclare("{var}.ordinal()", dftValue); } else if (isString(getterDeclareType) && attr.formatValue() != null) { CallerInfo info = convert.find(Number.class, String.class, String.class); String mapper = info.toString(null, strWrapped(attr.formatValue())); t0 = mapping.onDeclare(mapper, dftValue); } else { t0 = warningAndIgnored(model); } } else { return null; } return t0; } /** * String -> boolean * byte|short|int|long|float|double -> boolean : number != 0 * Byte|Short|Integer|Long|Float|Double -> boolean {@link Character#forDigit(int, int)} * Boolean -> boolean * * @param model * * @return */ private String declare2Boolean(final MappingModel model, Manager manager) { final String booleanWrappedType = Boolean.class.getCanonicalName(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (!isPrimitiveBoolean(setterDeclareType) && !booleanWrappedType.equals(setterDeclareType)) { return null; } // 基本数据类型 final MappingManager mapping = manager.getMapping(); if (isPrimitiveNumber(getterDeclareType)) { return mapping.onDeclare("{var} != 0", null); } else if (isPrimitiveBoolean(getterDeclareType)) { return mapping.onDeclare("{var}", null); } final String dftValue = manager.staticVarForDefaultBooleanOnDeclare(); if (isString(getterDeclareType)) { String mapper = "{type0}.parseBoolean({var})"; mapper = Replacer.type0.replace(mapper, manager.onImported(booleanWrappedType)); return mapping.onDeclare(mapper, dftValue); } // Number if (isWrappedNumber(getterDeclareType)) { String staticVar = manager.staticVarForDefaultNumberValueOf(getterDeclareType, "0"); String mapper = "{name}.equals({var})"; mapper = Replacer.name.replace(mapper, staticVar); return mapping.onDeclare(mapper, dftValue); } // Boolean if (isTypeof(getterDeclareType, Boolean.class)) { return mapping.onDeclare("{var}", dftValue); } return warningAndIgnored(model); } /** * char|Character -> char * byte|short|int|long|float|double -> char {@link Character#forDigit(int, int)} * Byte|Short|Integer|Long|Float|Double -> char {@link Character#forDigit(int, int)} *

* char|Character -> Character * byte|short|int|long|float|double -> Character {@link Character#forDigit(int, int)} * Byte|Short|Integer|Long|Float|Double -> Character {@link Character#forDigit(int, int)} * * @param model * * @return */ private String declare2Char(final MappingModel model, Manager manager) { String t0; final String wrappedType = Character.class.getCanonicalName(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (!StringUtils.isPrimitiveChar(setterDeclareType) && !isTypeof(setterDeclareType, wrappedType)) { return null; } final MappingManager mapping = manager.getMapping(); final ConvertManager convert = manager.ofConvert(); final String dftValue = manager.staticVarForDefaultChar(); if (StringUtils.isPrimitiveChar(getterDeclareType)) { t0 = convert.onSameType(); } else if (isTypeof(getterDeclareType, wrappedType)) { t0 = convert.onMapping(dftValue, "{var}", setterDeclareType, getterDeclareType); } else if (isPrimitiveNumber(getterDeclareType)) { t0 = "{toName}.{setterName}(Character.forDigit({cast}{fromName}.{getterName}(), 10));"; t0 = Replacer.cast.replace(t0, isCompatible(INT, getterDeclareType) ? "" : "(int)"); } else if (isSubtypeOf(getterDeclareType, Number.class)) { String mapper = "{setterType}.forDigit({var}.intValue(), 10)"; t0 = convert.onMapping(dftValue, mapper, wrappedType, getterDeclareType); } else { t0 = warningAndIgnored(model); } return t0; } /** * byte、short、int、long、float、double -> {@link BigDecimal#valueOf(long)}, {@link BigDecimal#valueOf(double)} * Byte、Short、Integer、Long、Float、Double -> {@link BigDecimal#valueOf(long)} *

* String -> {@link BigDecimal#BigDecimal(String)}, {@link BigDecimal#BigDecimal(BigInteger)} *

* char|Character -> {@link BigDecimal#valueOf(long)} * * @param model * * @return */ private String declare2BigDecimal(final MappingModel model, Manager manager) { String t0; final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (!isTypeof(setterDeclareType, BigDecimal.class)) { return null; } final ConvertManager convert = manager.ofConvert(); final MappingManager mapping = manager.getMapping(); final String dftValue = manager.staticVarForDefaultBigDecimal(); if (isTypeof(getterDeclareType, BigDecimal.class)) { return mapping.onDeclare(null, dftValue); } else if (isPrimitiveNumber(getterDeclareType) || isWrappedNumber(getterDeclareType)) { return mapping.onDeclare("{setterType}.valueOf({var})", dftValue); } else if (isTypeof(getterDeclareType, BigInteger.class)) { return mapping.onDeclare("new {setterType}({var})", dftValue); } else if (isSubtypeOf(getterDeclareType, Number.class)) { CallerInfo mapper = convert.find(BigDecimal.class, Number.class); t0 = mapping.onDeclare(mapper.toString(), dftValue); } else if (isEnum(getterDeclareType)) { return mapping.onDeclare("{setterType}.valueOf({var}.ordinal())", dftValue); } else if (isString(getterDeclareType)) { String format = model.getAttr().formatValue(); if (format == null) { String mapper = "new {setterType}({var})"; return mapping.onDeclare(mapper, dftValue); } else { CallerInfo mapper = convert.find(setterDeclareType, String.class, String.class); t0 = mapping.onDeclare(mapper.toString(null, strWrapped(format)), dftValue); } } else { t0 = warningAndIgnored(model); } return t0; } /** * byte、short、int、long、float、double -> {@link BigInteger#valueOf(long)} * Byte、Short、Integer、Long、Float、Double -> {@link BigInteger#valueOf(long)} * String -> {@link BigInteger#BigInteger(String)} * char|Character -> {@link BigInteger#valueOf(long)} * * @param model * * @return */ private String declare2BigInteger(final MappingModel model, Manager manager) { String t0; final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (!isTypeof(setterDeclareType, BigInteger.class)) { return null; } final ConvertManager convert = manager.ofConvert(); final MappingManager mapping = manager.getMapping(); final String formatVal = model.getAttr().formatValue(); final String dftValue = manager.staticVarForDefaultBigInteger(); if (isTypeof(getterDeclareType, BigInteger.class)) { return convert.onSameType(dftValue, getterDeclareType); } else if (isPrimitiveNumber(getterDeclareType)) { String cast = castPrimitiveIfGtTop(getterDeclareType, LONG); String mapper = "{setterType}.valueOf({cast}{var})"; mapper = Replacer.cast.replace(mapper, cast); return mapping.onDeclare(mapper, dftValue); } else if (isSubtypeOf(getterDeclareType, Number.class)) { return mapping.onDeclare("{setterType}.valueOf({var}.longValue())", dftValue); } else if (isEnum(getterDeclareType)) { return mapping.onDeclare("{setterType}.valueOf({var}.ordinal())", dftValue); } else if (isString(getterDeclareType)) { if (formatVal == null) { return mapping.onDeclare("new {setterType}({var})", dftValue); } else { CallerInfo mapper = convert.find(setterDeclareType, String.class, String.class); t0 = mapping.onDeclare(mapper.toString(null, strWrapped(formatVal)), dftValue); } } else { t0 = warningAndIgnored(model); } return t0; } /** * byte|short|int|long|float|double * Byte|Short|Integer|Long|Float|Double *

* {@link LocalDateTime#LocalDateTime(long)} * {@link LocalDate#LocalDate(long)} * {@link LocalTime#LocalTime(long)} * {@link Duration#Duration(long)} * {@link YearMonth#YearMonth(long)} * {@link MonthDay#MonthDay(long)} * {@link DateTime#DateTime(long)} * {@link Instant#Instant(long)} * {@link MutableDateTime#MutableDateTime(long)} * {@link MutablePeriod#MutablePeriod(long)} * * @param model * * @return */ private String declare2JodaTime(final MappingModel model, Manager manager) { if (!Imported.JODA_TIME) { return null; } String t0; final ConvertManager convert = manager.ofConvert(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (isTypeofAny(setterDeclareType, MutableDateTime.class, DateTime.class, LocalDateTime.class, LocalDate.class, LocalTime.class, MutablePeriod.class, Duration.class, YearMonth.class, Instant.class, MonthDay.class)) { if (isPrimitiveNumber(getterDeclareType)) { String cast = isCompatible(LONG, getterDeclareType) ? "" : "(long)"; t0 = "{toName}.{setterName}(new {setterType}({cast}{fromName}.{getterName}()));"; t0 = Replacer.cast.replace(t0, cast); t0 = Replacer.setterType.replace(t0, manager.onImported(setterDeclareType)); } else if (isSubtypeOf(getterDeclareType, Number.class)) { String mapper = "new {setterType}({var}.longValue())"; t0 = convert.onMapping(null, mapper, setterDeclareType, getterDeclareType); } else if (isTypeof(setterDeclareType, Duration.class)) { if (isString(getterDeclareType)) { t0 = convert.onMapping(null, "{setterType}.parse({var})", setterDeclareType, getterDeclareType); } else { t0 = warningAndIgnored(model); } } else if (isTypeofAny(setterDeclareType, MutableDateTime.class, DateTime.class, LocalDateTime.class, LocalDate.class, LocalTime.class, YearMonth.class, MonthDay.class, Instant.class)) { if (isString(getterDeclareType)) { String format = defaultDatePattern(setterDeclareType, model.getAttr().formatValue()); String dftFormat = manager.staticVarForJodaDateTimeFormatter(format); if (isNullString(dftFormat)) { t0 = convert.onMapping(null, "{setterType}.parse({var})", setterDeclareType, String.class); } else { t0 = convert.useMapping(null, () -> { String tx = "{setterType}.parse({var}, {format})"; return Replacer.format.replace(tx, dftFormat); }, setterDeclareType, String.class); } } else if (isSubtypeOf(getterDeclareType, Date.class) || isTypeof(getterDeclareType, Calendar.class)) { t0 = convert.onMapping(null, "new {setterType}({var})", setterDeclareType, getterDeclareType); } else { t0 = warningAndIgnored(model); } } else { t0 = warningAndIgnored(model); } return t0; } return null; } private String declare2Jdk8Time(final MappingModel model, Manager manager) { final ConvertManager convert = manager.ofConvert(); final MappingManager mapping = manager.getMapping(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (isString(getterDeclareType) && isSubtypeOf(setterDeclareType, TemporalAccessor.class)) { String declareVal = defaultDatePattern(setterDeclareType, model.getAttr().formatValue()); String format = manager.staticVarForDateTimeFormatter(declareVal); if (isNullString(format)) { return mapping.onDeclare("{setterType}.parse({var})", null); } else { String mapper = "{setterType}.from({format}.parse({var}))"; mapper = Replacer.format.replace(mapper, format); return mapping.onDeclare(mapper, null); } } if (!isTypeofJdk8DateTime(setterDeclareType)) { return null; } String t0; if (isPrimitiveNumber(getterDeclareType)) { String getterType = isCompatible(LONG, getterDeclareType) ? LONG : DOUBLE; String mapper = convert.find(setterDeclareType, getterType).toString(); t0 = mapping.onDeclare(mapper, null); } else if (isSubtypeOf(getterDeclareType, Number.class)) { t0 = convert.onConvertSimple(setterDeclareType, Number.class); } else if (isSubtypeOf(getterDeclareType, Date.class)) { t0 = convert.onConvertSimple(setterDeclareType, Date.class); } else if (isTypeof(getterDeclareType, Calendar.class)) { t0 = convert.onConvertSimple(setterDeclareType, Calendar.class); } else if (Imported.JODA_TIME) { if (isSubtypeOf(getterDeclareType, ReadableInstant.class)) { t0 = convert.onConvertSimple(setterDeclareType, ReadableInstant.class); } else if (isTypeofAny(getterDeclareType, LocalDateTime.class, LocalDate.class)) { t0 = convert.onConvertSimple(setterDeclareType, getterDeclareType); } else { t0 = null; } } else { t0 = null; } if (t0 == null) { t0 = convert.onConvertSimple(setterDeclareType, getterDeclareType); } return t0 == null ? warningAndIgnored(model) : t0; } /** long -> Date, Timestamp, java.sql.Date, Calendar */ private String declare2Date(final MappingModel model, Manager manager) { String t0; final MappingManager mapping = manager.getMapping(); final ConvertManager convert = manager.ofConvert(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (isTypeofAny(setterDeclareType, Date.class, java.sql.Date.class, Timestamp.class, Time.class)) { if (isPrimitiveNumber(getterDeclareType)) { String getterType = isCompatible(LONG, getterDeclareType) ? LONG : DOUBLE; CallerInfo info = convert.find(setterDeclareType, getterType); t0 = mapping.get(setterDeclareType, getterType, info.toString(), null); } else if (isSubtypeOf(getterDeclareType, Number.class)) { CallerInfo info = convert.find(setterDeclareType, Number.class); t0 = mapping.onDeclare(info.toString(), null); } else if (isTypeof(getterDeclareType, Calendar.class)) { CallerInfo info = convert.find(setterDeclareType, Calendar.class); t0 = mapping.onDeclare(info.toString(), null); } else if (isTypeofJdk8Date(getterDeclareType)) { CallerInfo info = convert.find(setterDeclareType, getterDeclareType); t0 = mapping.onDeclare(info.toString(), null); } else if (isString(getterDeclareType)) { final String format = defaultDatePattern(setterDeclareType, model.getAttr().formatValue()); if (isNullString(format)) { CallerInfo info = convert.find(setterDeclareType, getterDeclareType); t0 = mapping.onDeclare(info.toString(), null); } else { CallerInfo info = convert.find(setterDeclareType, String.class, String.class); String mapper = info.toString(null, strWrapped(format)); t0 = mapping.onDeclare(mapper, null); } } else { t0 = onImportedJodaTime(model, convert); } return t0; } else { return null; } } private String declare2Calendar(final MappingModel model, Manager manager) { String t0; final MappingManager mapping = manager.getMapping(); final ConvertManager convert = manager.ofConvert(); final String setterDeclareType = model.getSetterDeclareType(); final String getterDeclareType = model.getGetterDeclareType(); if (isTypeof(setterDeclareType, Calendar.class)) { if (isPrimitiveNumber(getterDeclareType)) { String getterType = isPrimitiveSubtypeOf(getterDeclareType, LONG) ? LONG : DOUBLE; CallerInfo info = convert.find(setterDeclareType, getterType); t0 = mapping.get(setterDeclareType, getterType, info.toString(), null); } else if (isSubtypeOf(getterDeclareType, Number.class)) { CallerInfo info = convert.find(setterDeclareType, Number.class); t0 = mapping.onDeclare(info.toString(), null); } else if (isSubtypeOf(getterDeclareType, Date.class)) { CallerInfo info = convert.find(setterDeclareType, Date.class); t0 = mapping.onDeclare(info.toString(), null); } else if (isTypeofJdk8Date(getterDeclareType)) { CallerInfo info = convert.find(setterDeclareType, getterDeclareType); t0 = mapping.onDeclare(info.toString(), null); } else if (isString(getterDeclareType)) { final String format = defaultDatePattern(setterDeclareType, model.getAttr().formatValue()); if (isNullString(format)) { CallerInfo info = convert.find(setterDeclareType, getterDeclareType); t0 = mapping.onDeclare(info.toString(), null); } else { CallerInfo info = convert.find(setterDeclareType, String.class, String.class); String mapper = info.toString(null, strWrapped(format)); t0 = mapping.onDeclare(mapper, null); } } else { t0 = onImportedJodaTime(model, convert); } return t0; } return null; } private String defaultDatePattern(String type, String pattern) { return pattern == null ? dateFormats.getOrDefault(type, DATE_FORMAT) : pattern; } private String onImportedJodaTime(MappingModel model, ConvertManager convert) { String t0, setterDeclareType = model.getSetterDeclareType(), getterDeclareType = model.getGetterDeclareType(); if (Imported.JODA_TIME) { if (isSubtypeOf(getterDeclareType, ReadableInstant.class)) { t0 = convert.useConvert(null, STRINGIFY, setterDeclareType, ReadableInstant.class); } else if (isTypeofAny(getterDeclareType, LocalDateTime.class, LocalDate.class)) { t0 = convert.useConvert(null, STRINGIFY, setterDeclareType, getterDeclareType); } else { t0 = warningAndIgnored(model); } } else { t0 = warningAndIgnored(model); } return t0; } private String onDeclareCompleted(String t0, MappingModel model) { if (t0 != null) { t0 = Replacer.fromName.replace(t0, model.getFromName()); t0 = Replacer.toName.replace(t0, model.getToName()); t0 = Replacer.setterName.replace(t0, model.getSetterName()); t0 = Replacer.getterName.replace(t0, model.getGetterName()); if (t0.contains("{var}")) { t0 = Replacer.var.replace(t0, nextVarName()); } if (t0.contains("{var0}")) { t0 = Replacer.var0.replace(t0, nextVarName()); } if (t0.contains("{var1}")) { t0 = Replacer.var1.replace(t0, nextVarName()); } } return t0; } private String warningAndIgnored(final MappingModel model) { String fromType = getSimpleName(model.getFromClassname()); String toType = getSimpleName(model.getToClassname()); Object[] values = { toType, model.getSetterName(), model.getSetterFinalType(),// fromType, model.getGetterName(), model.getGetterFinalType() }; Logger.printWarn(TEMPLATE, values); this.warned = true; return null; } private final static String TEMPLATE = "【已忽略】'{}.{}({})' 不兼容 '{}.{}()' 返回值类型: {}"; private final AtomicInteger indexer = new AtomicInteger(); private AtomicInteger getIndexer() { return indexer; } private boolean isWarned() { return warned; } private void unWarned() { this.warned = false; } private String nextVarName() { return nextVarName(getIndexer()); } private static String nextVarName(AtomicInteger indexer) { return "var" + indexer.getAndIncrement(); } private static String castPrimitiveIfGtTop(String thisPrimitive, String topPrimitive) { return isPrimitiveSubtypeOf(thisPrimitive, topPrimitive) ? "" : bracketed(topPrimitive); } private static String castPrimitiveIfLtLow(String thisPrimitive, String topPrimitive) { return isCompatible(thisPrimitive, topPrimitive) ? "" : bracketed(thisPrimitive); } private static boolean isPrimitiveSubtypeOf(String thisType, String thatType) { return isCompatible(thatType, thisType); } private static boolean isCompatible(String thisType, String thatType) { String all = "byte,short,int,long,float,double"; int thisIdx = all.indexOf(thisType); int thatIdx = all.indexOf(thatType); return thisIdx >= thatIdx; } private final Function STRINGIFY = Object::toString; private static boolean isString(String value) { return isTypeof(value, String.class); } private static boolean isEnum(String value) { if (value == null) { return false; } TypeElement elem = EnvUtils.getUtils().getTypeElement(value); return elem != null && elem.getKind() == ElementKind.ENUM; } private static boolean isTypeofJdk8Date(String type) { return isTypeofAny(type, java.time.LocalDateTime.class, java.time.ZonedDateTime.class, java.time.OffsetDateTime.class, java.time.Instant.class, java.time.LocalDate.class); } private static boolean isTypeofJdk8DateTime(String type) { return isTypeofJdk8Date(type) || isTypeof(type, java.time.LocalTime.class); } private static boolean isSubtypeOf(String actualType, Class superclass) { return isSubtypeOf(actualType, superclass.getCanonicalName()); } private static boolean isSubtypeOfAny(String actualType, Class... superclasses) { if (superclasses != null) { for (Class superclass : superclasses) { if (isSubtypeOf(actualType, superclass)) { return true; } } } return false; } private static boolean isSubtypeOf(String actualType, String superClass) { if (actualType == null || superClass == null) { return false; } Elements utils = EnvUtils.getUtils(); TypeElement elem1 = utils.getTypeElement(actualType); TypeElement elem2 = utils.getTypeElement(superClass); return elem1 != null && elem2 != null && EnvUtils.getTypes().isSubtype(elem1.asType(), elem2.asType()); } private static boolean isFormattable(String fmt, String actualType, Class... superclasses) { return !isNullString(fmt) && isSubtypeOfAny(actualType, superclasses); } private static boolean isJodaFormattable(String fmt, String type) { return Imported.JODA_TIME// && isFormattable(fmt, type, ReadableInstant.class, ReadablePartial.class); } private static boolean isNullString(String dftVal) { return dftVal == null; } private static String strWrapped(String str) { return '"' + str + '"'; } private static String bracketed(String str) { return "(" + str + ")"; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy