001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.util; 017 018import java.math.BigDecimal; 019import java.math.BigInteger; 020import java.time.LocalDate; 021import java.time.LocalDateTime; 022import java.time.LocalTime; 023import java.time.temporal.Temporal; 024import java.util.Date; 025 026public class ConvertUtil { 027 028 private ConvertUtil() { 029 } 030 031 @SuppressWarnings("rawtypes") 032 public static Object convert(Object value, Class targetClass) { 033 return convert(value, targetClass, false); 034 } 035 036 @SuppressWarnings({"unchecked", "rawtypes"}) 037 public static Object convert(Object value, Class targetClass, boolean ignoreConvertError) { 038 if (value == null && targetClass.isPrimitive()) { 039 return getPrimitiveDefaultValue(targetClass); 040 } 041 if (value == null || (targetClass != String.class && value.getClass() == String.class 042 && StringUtil.isBlank((String) value))) { 043 return null; 044 } 045 if (value.getClass().isAssignableFrom(targetClass)) { 046 return value; 047 } 048 if (targetClass == String.class) { 049 return value.toString(); 050 } else if (targetClass == Integer.class || targetClass == int.class) { 051 if (value instanceof Number) { 052 return ((Number) value).intValue(); 053 } 054 return Integer.parseInt(value.toString()); 055 } else if (targetClass == Long.class || targetClass == long.class) { 056 if (value instanceof Number) { 057 return ((Number) value).longValue(); 058 } 059 return Long.parseLong(value.toString()); 060 } else if (targetClass == Double.class || targetClass == double.class) { 061 if (value instanceof Number) { 062 return ((Number) value).doubleValue(); 063 } 064 return Double.parseDouble(value.toString()); 065 } else if (targetClass == Float.class || targetClass == float.class) { 066 if (value instanceof Number) { 067 return ((Number) value).floatValue(); 068 } 069 return Float.parseFloat(value.toString()); 070 } else if (targetClass == Boolean.class || targetClass == boolean.class) { 071 String v = value.toString().toLowerCase(); 072 if ("1".equals(v) || "true".equalsIgnoreCase(v)) { 073 return Boolean.TRUE; 074 } else if ("0".equals(v) || "false".equalsIgnoreCase(v)) { 075 return Boolean.FALSE; 076 } else { 077 throw new RuntimeException("Can not parse to boolean type of value: \"" + value + "\""); 078 } 079 } else if (targetClass == java.math.BigDecimal.class) { 080 return new java.math.BigDecimal(value.toString()); 081 } else if (targetClass == java.math.BigInteger.class) { 082 return new java.math.BigInteger(value.toString()); 083 } else if (targetClass == byte[].class) { 084 return value.toString().getBytes(); 085 } else if (targetClass == Date.class) { 086 return DateUtil.parseDate(value); 087 } else if (targetClass == LocalDateTime.class) { 088 return toLocalDateTime(value); 089 } else if (targetClass == LocalDate.class) { 090 return DateUtil.toLocalDate(DateUtil.parseDate(value)); 091 } else if (targetClass == LocalTime.class) { 092 return DateUtil.toLocalTime(DateUtil.parseDate(value)); 093 } else if (targetClass == Short.class || targetClass == short.class) { 094 if (value instanceof Number) { 095 return ((Number) value).shortValue(); 096 } 097 return Short.parseShort(value.toString()); 098 } else if (targetClass.isEnum()) { 099 EnumWrapper<?> enumWrapper = EnumWrapper.of(targetClass); 100 if (enumWrapper.hasEnumValueAnnotation()) { 101 return enumWrapper.getEnum(value); 102 } else if (value instanceof String) { 103 return Enum.valueOf(targetClass, value.toString()); 104 } 105 } 106 if (ignoreConvertError) { 107 return null; 108 } else { 109 throw new IllegalArgumentException("Can not convert \"" + value + "\" to type\"" + targetClass.getName() + "\"."); 110 } 111 } 112 113 114 //Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE 115 public static Object getPrimitiveDefaultValue(Class<?> paraClass) { 116 if (paraClass == int.class || paraClass == long.class || paraClass == float.class || paraClass == double.class) { 117 return 0; 118 } else if (paraClass == boolean.class) { 119 return Boolean.FALSE; 120 } else if (paraClass == short.class) { 121 return (short) 0; 122 } else if (paraClass == byte.class) { 123 return (byte) 0; 124 } else if (paraClass == char.class) { 125 return '\u0000'; 126 } else { 127 throw new IllegalArgumentException("Can not get primitive default value for type: " + paraClass); 128 } 129 } 130 131 132 public static Integer toInt(Object i) { 133 if (i instanceof Integer) { 134 return (Integer) i; 135 } else if (i instanceof Number) { 136 return ((Number) i).intValue(); 137 } 138 return i != null ? Integer.parseInt(i.toString()) : null; 139 } 140 141 public static Long toLong(Object l) { 142 if (l instanceof Long) { 143 return (Long) l; 144 } else if (l instanceof Number) { 145 return ((Number) l).longValue(); 146 } 147 return l != null ? Long.parseLong(l.toString()) : null; 148 } 149 150 public static Double toDouble(Object d) { 151 if (d instanceof Double) { 152 return (Double) d; 153 } else if (d instanceof Number) { 154 return ((Number) d).doubleValue(); 155 } 156 157 return d != null ? Double.parseDouble(d.toString()) : null; 158 } 159 160 public static BigDecimal toBigDecimal(Object b) { 161 if (b instanceof BigDecimal) { 162 return (BigDecimal) b; 163 } else if (b != null) { 164 return new BigDecimal(b.toString()); 165 } else { 166 return null; 167 } 168 } 169 170 public static BigInteger toBigInteger(Object b) { 171 if (b instanceof BigInteger) { 172 return (BigInteger) b; 173 } 174 // 数据类型 id(19 number)在 Oracle Jdbc 下对应的是 BigDecimal, 175 // 但是在 MySql 下对应的是 BigInteger,这会导致在 MySql 下生成的代码无法在 Oracle 数据库中使用 176 if (b instanceof BigDecimal) { 177 return ((BigDecimal) b).toBigInteger(); 178 } else if (b instanceof Number) { 179 return BigInteger.valueOf(((Number) b).longValue()); 180 } else if (b instanceof String) { 181 return new BigInteger((String) b); 182 } 183 184 return (BigInteger) b; 185 } 186 187 public static Float toFloat(Object f) { 188 if (f instanceof Float) { 189 return (Float) f; 190 } else if (f instanceof Number) { 191 return ((Number) f).floatValue(); 192 } 193 return f != null ? Float.parseFloat(f.toString()) : null; 194 } 195 196 197 public static Short toShort(Object s) { 198 if (s instanceof Short) { 199 return (Short) s; 200 } else if (s instanceof Number) { 201 return ((Number) s).shortValue(); 202 } 203 return s != null ? Short.parseShort(s.toString()) : null; 204 } 205 206 207 public static Byte toByte(Object b) { 208 if (b instanceof Byte) { 209 return (Byte) b; 210 } else if (b instanceof Number) { 211 return ((Number) b).byteValue(); 212 } 213 return b != null ? Byte.parseByte(b.toString()) : null; 214 } 215 216 public static Boolean toBoolean(Object b) { 217 if (b instanceof Boolean) { 218 return (Boolean) b; 219 } else if (b == null) { 220 return null; 221 } 222 223 // 支持 Number 之下的整数类型 224 if (b instanceof Number) { 225 int n = ((Number) b).intValue(); 226 if (n == 1) { 227 return Boolean.TRUE; 228 } else if (n == 0) { 229 return Boolean.FALSE; 230 } 231 throw new IllegalArgumentException("Can not support convert: \"" + b + "\" to boolean."); 232 } 233 234 // 支持 String 235 if (b instanceof String) { 236 String s = b.toString(); 237 if ("true".equalsIgnoreCase(s) || "1".equals(s)) { 238 return Boolean.TRUE; 239 } else if ("false".equalsIgnoreCase(s) || "0".equals(s)) { 240 return Boolean.FALSE; 241 } 242 } 243 244 return (Boolean) b; 245 } 246 247 248 public static Date toDate(Object o) { 249 if (o instanceof Date) { 250 return (Date) o; 251 } 252 253 if (o instanceof Temporal) { 254 if (o instanceof LocalDateTime) { 255 return DateUtil.toDate((LocalDateTime) o); 256 } 257 if (o instanceof LocalDate) { 258 return DateUtil.toDate((LocalDate) o); 259 } 260 if (o instanceof LocalTime) { 261 return DateUtil.toDate((LocalTime) o); 262 } 263 } 264 265 if (o instanceof String) { 266 String s = (String) o; 267 return DateUtil.parseDate(s); 268 } 269 270 return (java.util.Date) o; 271 } 272 273 274 public static LocalDateTime toLocalDateTime(Object o) { 275 if (o instanceof LocalDateTime) { 276 return (LocalDateTime) o; 277 } 278 if (o instanceof java.util.Date) { 279 return DateUtil.toLocalDateTime((java.util.Date) o); 280 } 281 if (o instanceof LocalDate) { 282 return ((LocalDate) o).atStartOfDay(); 283 } 284 if (o instanceof LocalTime) { 285 return LocalDateTime.of(LocalDate.now(), (LocalTime) o); 286 } 287 288 if (o instanceof String) { 289 String s = (String) o; 290 return DateUtil.parseLocalDateTime(s); 291 } 292 293 return (LocalDateTime) o; 294 } 295 296}