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 public static Object convert(Object value, Class targetClass) { 031 return convert(value, targetClass, false); 032 } 033 034 public static Object convert(Object value, Class targetClass, boolean ignoreConvertError) { 035 if (value == null && targetClass.isPrimitive()) { 036 return getPrimitiveDefaultValue(targetClass); 037 } 038 if (value == null || (targetClass != String.class && value.getClass() == String.class 039 && StringUtil.isBlank((String) value))) { 040 return null; 041 } 042 if (value.getClass().isAssignableFrom(targetClass)) { 043 return value; 044 } 045 if (targetClass == String.class) { 046 return value.toString(); 047 } else if (targetClass == Integer.class || targetClass == int.class) { 048 if (value instanceof Number) { 049 return ((Number) value).intValue(); 050 } 051 return Integer.parseInt(value.toString()); 052 } else if (targetClass == Long.class || targetClass == long.class) { 053 if (value instanceof Number) { 054 return ((Number) value).longValue(); 055 } 056 return Long.parseLong(value.toString()); 057 } else if (targetClass == Double.class || targetClass == double.class) { 058 if (value instanceof Number) { 059 return ((Number) value).doubleValue(); 060 } 061 return Double.parseDouble(value.toString()); 062 } else if (targetClass == Float.class || targetClass == float.class) { 063 if (value instanceof Number) { 064 return ((Number) value).floatValue(); 065 } 066 return Float.parseFloat(value.toString()); 067 } else if (targetClass == Boolean.class || targetClass == boolean.class) { 068 String v = value.toString().toLowerCase(); 069 if ("1".equals(v) || "true".equalsIgnoreCase(v)) { 070 return Boolean.TRUE; 071 } else if ("0".equals(v) || "false".equalsIgnoreCase(v)) { 072 return Boolean.FALSE; 073 } else { 074 throw new RuntimeException("Can not parse to boolean type of value: \"" + value + "\""); 075 } 076 } else if (targetClass == java.math.BigDecimal.class) { 077 return new java.math.BigDecimal(value.toString()); 078 } else if (targetClass == java.math.BigInteger.class) { 079 return new java.math.BigInteger(value.toString()); 080 } else if (targetClass == byte[].class) { 081 return value.toString().getBytes(); 082 } else if (targetClass == Date.class) { 083 return DateUtil.parseDate(value); 084 } else if (targetClass == LocalDateTime.class) { 085 return toLocalDateTime(value); 086 } else if (targetClass == LocalDate.class) { 087 return DateUtil.toLocalDate(DateUtil.parseDate(value)); 088 } else if (targetClass == LocalTime.class) { 089 return DateUtil.toLocalTime(DateUtil.parseDate(value)); 090 } else if (targetClass == Short.class || targetClass == short.class) { 091 if (value instanceof Number) { 092 return ((Number) value).shortValue(); 093 } 094 return Short.parseShort(value.toString()); 095 } else if (targetClass.isEnum()) { 096 EnumWrapper enumWrapper = EnumWrapper.of(targetClass); 097 if (enumWrapper.hasEnumValueAnnotation()) { 098 return enumWrapper.getEnum(value); 099 } else if (value instanceof String) { 100 return Enum.valueOf(targetClass, value.toString()); 101 } 102 } 103 104 if (ignoreConvertError) { 105 return null; 106 } else { 107 throw new IllegalArgumentException("Can not convert \"" + value + "\" to type\"" + targetClass.getName() + "\"."); 108 } 109 } 110 111 112 //Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE 113 public static Object getPrimitiveDefaultValue(Class<?> paraClass) { 114 if (paraClass == int.class || paraClass == long.class || paraClass == float.class || paraClass == double.class) { 115 return 0; 116 } else if (paraClass == boolean.class) { 117 return Boolean.FALSE; 118 } else if (paraClass == short.class) { 119 return (short) 0; 120 } else if (paraClass == byte.class) { 121 return (byte) 0; 122 } else if (paraClass == char.class) { 123 return '\u0000'; 124 } else { 125 throw new IllegalArgumentException("Can not get primitive default value for type: " + paraClass); 126 } 127 } 128 129 130 public static Integer toInt(Object i) { 131 if (i instanceof Integer) { 132 return (Integer) i; 133 } else if (i instanceof Number) { 134 return ((Number) i).intValue(); 135 } 136 return i != null ? Integer.parseInt(i.toString()) : null; 137 } 138 139 public static Long toLong(Object l) { 140 if (l instanceof Long) { 141 return (Long) l; 142 } else if (l instanceof Number) { 143 return ((Number) l).longValue(); 144 } 145 return l != null ? Long.parseLong(l.toString()) : null; 146 } 147 148 public static Double toDouble(Object d) { 149 if (d instanceof Double) { 150 return (Double) d; 151 } else if (d instanceof Number) { 152 return ((Number) d).doubleValue(); 153 } 154 155 return d != null ? Double.parseDouble(d.toString()) : null; 156 } 157 158 public static BigDecimal toBigDecimal(Object b) { 159 if (b instanceof BigDecimal) { 160 return (BigDecimal) b; 161 } else if (b != null) { 162 return new BigDecimal(b.toString()); 163 } else { 164 return null; 165 } 166 } 167 168 public static BigInteger toBigInteger(Object b) { 169 if (b instanceof BigInteger) { 170 return (BigInteger) b; 171 } 172 // 数据类型 id(19 number)在 Oracle Jdbc 下对应的是 BigDecimal, 173 // 但是在 MySql 下对应的是 BigInteger,这会导致在 MySql 下生成的代码无法在 Oracle 数据库中使用 174 if (b instanceof BigDecimal) { 175 return ((BigDecimal) b).toBigInteger(); 176 } else if (b instanceof Number) { 177 return BigInteger.valueOf(((Number) b).longValue()); 178 } else if (b instanceof String) { 179 return new BigInteger((String) b); 180 } 181 182 return (BigInteger) b; 183 } 184 185 public static Float toFloat(Object f) { 186 if (f instanceof Float) { 187 return (Float) f; 188 } else if (f instanceof Number) { 189 return ((Number) f).floatValue(); 190 } 191 return f != null ? Float.parseFloat(f.toString()) : null; 192 } 193 194 195 public static Short toShort(Object s) { 196 if (s instanceof Short) { 197 return (Short) s; 198 } else if (s instanceof Number) { 199 return ((Number) s).shortValue(); 200 } 201 return s != null ? Short.parseShort(s.toString()) : null; 202 } 203 204 205 public static Byte toByte(Object b) { 206 if (b instanceof Byte) { 207 return (Byte) b; 208 } else if (b instanceof Number) { 209 return ((Number) b).byteValue(); 210 } 211 return b != null ? Byte.parseByte(b.toString()) : null; 212 } 213 214 public static Boolean toBoolean(Object b) { 215 if (b instanceof Boolean) { 216 return (Boolean) b; 217 } else if (b == null) { 218 return null; 219 } 220 221 // 支持 Number 之下的整数类型 222 if (b instanceof Number) { 223 int n = ((Number) b).intValue(); 224 if (n == 1) { 225 return Boolean.TRUE; 226 } else if (n == 0) { 227 return Boolean.FALSE; 228 } 229 throw new IllegalArgumentException("Can not support convert: \"" + b + "\" to boolean."); 230 } 231 232 // 支持 String 233 if (b instanceof String) { 234 String s = b.toString(); 235 if ("true".equalsIgnoreCase(s) || "1".equals(s)) { 236 return Boolean.TRUE; 237 } else if ("false".equalsIgnoreCase(s) || "0".equals(s)) { 238 return Boolean.FALSE; 239 } 240 } 241 242 return (Boolean) b; 243 } 244 245 public static Number toNumber(Object o) { 246 if (o instanceof Number) { 247 return (Number) o; 248 } else if (o == null) { 249 return null; 250 } 251 String s = o.toString(); 252 return s.indexOf('.') != -1 ? Double.parseDouble(s) : Long.parseLong(s); 253 } 254 255 256 public static Date toDate(Object o) { 257 if (o instanceof Date) { 258 return (Date) o; 259 } 260 261 if (o instanceof Temporal) { 262 if (o instanceof LocalDateTime) { 263 return DateUtil.toDate((LocalDateTime) o); 264 } 265 if (o instanceof LocalDate) { 266 return DateUtil.toDate((LocalDate) o); 267 } 268 if (o instanceof LocalTime) { 269 return DateUtil.toDate((LocalTime) o); 270 } 271 } 272 273 if (o instanceof String) { 274 String s = (String) o; 275 return DateUtil.parseDate(s); 276 } 277 278 return (java.util.Date) o; 279 } 280 281 282 public static LocalDateTime toLocalDateTime(Object o) { 283 if (o instanceof LocalDateTime) { 284 return (LocalDateTime) o; 285 } 286 if (o instanceof java.util.Date) { 287 return DateUtil.toLocalDateTime((java.util.Date) o); 288 } 289 if (o instanceof LocalDate) { 290 return ((LocalDate) o).atStartOfDay(); 291 } 292 if (o instanceof LocalTime) { 293 return LocalDateTime.of(LocalDate.now(), (LocalTime) o); 294 } 295 296 if (o instanceof String) { 297 String s = (String) o; 298 return DateUtil.parseLocalDateTime(s); 299 } 300 301 return (LocalDateTime) o; 302 } 303}