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