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