001: /*
002: * Copyright 2006, 2007 Odysseus Software GmbH
003: *
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: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
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: */
016: package de.odysseus.el.misc;
017:
018: import java.beans.PropertyEditor;
019: import java.beans.PropertyEditorManager;
020: import java.math.BigDecimal;
021: import java.math.BigInteger;
022: import java.util.HashMap;
023:
024: import javax.el.ELException;
025:
026: /**
027: * Type Conversions as described in EL 2.1 specification (section 1.17).
028: */
029: public class TypeConversions {
030: private static final Long LONG_ZERO = Long.valueOf(0L);
031: private static final HashMap<Class<?>, Class<?>> WRAPPER_TYPES = new HashMap<Class<?>, Class<?>>();
032:
033: static {
034: WRAPPER_TYPES.put(Boolean.TYPE, Boolean.class);
035: WRAPPER_TYPES.put(Character.TYPE, Character.class);
036: WRAPPER_TYPES.put(Byte.TYPE, Byte.class);
037: WRAPPER_TYPES.put(Short.TYPE, Short.class);
038: WRAPPER_TYPES.put(Integer.TYPE, Integer.class);
039: WRAPPER_TYPES.put(Long.TYPE, Long.class);
040: WRAPPER_TYPES.put(Float.TYPE, Float.class);
041: WRAPPER_TYPES.put(Double.TYPE, Double.class);
042: }
043:
044: public static final Boolean coerceToBoolean(Object value) {
045: if (value == null || "".equals(value)) {
046: return Boolean.FALSE;
047: }
048: if (value instanceof Boolean) {
049: return (Boolean) value;
050: }
051: if (value instanceof String) {
052: return Boolean.valueOf((String) value);
053: }
054: throw new ELException(LocalMessages.get("error.coerce.type",
055: value.getClass(), Boolean.class));
056: }
057:
058: public static final Character coerceToCharacter(Object value) {
059: if (value == null || "".equals(value)) {
060: return Character.valueOf((char) 0);
061: }
062: if (value instanceof Character) {
063: return (Character) value;
064: }
065: if (value instanceof Number) {
066: return new Character((char) ((Number) value).shortValue());
067: }
068: if (value instanceof String) {
069: return new Character(((String) value).charAt(0));
070: }
071: throw new ELException(LocalMessages.get("error.coerce.type",
072: value.getClass(), Character.class));
073: }
074:
075: private static final Number coerceStringToNumber(String value,
076: Class<? extends Number> type) {
077: try {
078: if (type == BigDecimal.class) {
079: return new BigDecimal(value);
080: }
081: if (type == BigInteger.class) {
082: return new BigInteger(value);
083: }
084: if (type == Byte.class) {
085: return Byte.valueOf(value);
086: }
087: if (type == Short.class) {
088: return Short.valueOf(value);
089: }
090: if (type == Integer.class) {
091: return Integer.valueOf(value);
092: }
093: if (type == Long.class) {
094: return Long.valueOf(value);
095: }
096: if (type == Float.class) {
097: return Float.valueOf(value);
098: }
099: if (type == Double.class) {
100: return Double.valueOf(value);
101: }
102: } catch (NumberFormatException e) {
103: throw new ELException(LocalMessages.get(
104: "error.coerce.value", value, type));
105: }
106: throw new ELException(LocalMessages.get("error.coerce.type",
107: String.class, type));
108: }
109:
110: private static final Number coerceNumberToNumber(Number value,
111: Class<? extends Number> type) {
112: if (type.isInstance(value)) {
113: return value;
114: }
115: if (type == BigInteger.class) {
116: if (value instanceof BigDecimal) {
117: return ((BigDecimal) value).toBigInteger();
118: }
119: return BigInteger.valueOf((value).longValue());
120: }
121: if (type == BigDecimal.class) {
122: if (value instanceof BigInteger) {
123: return new BigDecimal((BigInteger) value);
124: }
125: return new BigDecimal(value.doubleValue());
126: }
127: if (type == Byte.class) {
128: return Byte.valueOf(value.byteValue());
129: }
130: if (type == Short.class) {
131: return Short.valueOf(value.shortValue());
132: }
133: if (type == Integer.class) {
134: return Integer.valueOf(value.intValue());
135: }
136: if (type == Long.class) {
137: return Long.valueOf(value.longValue());
138: }
139: if (type == Float.class) {
140: return Float.valueOf(value.floatValue());
141: }
142: if (type == Double.class) {
143: return Double.valueOf(value.doubleValue());
144: }
145: throw new ELException(LocalMessages.get("error.coerce.type",
146: value.getClass(), type));
147: }
148:
149: @SuppressWarnings("unchecked")
150: public static final <T extends Number> T coerceToNumber(
151: Object value, Class<T> type) {
152: if (value == null || "".equals(value)) {
153: return (T) coerceNumberToNumber(LONG_ZERO, type);
154: }
155: if (value instanceof Character) {
156: return (T) coerceNumberToNumber(Short
157: .valueOf((short) ((Character) value).charValue()),
158: type);
159: }
160: if (value instanceof Number) {
161: return (T) coerceNumberToNumber((Number) value, type);
162: }
163: if (value instanceof String) {
164: return (T) coerceStringToNumber((String) value, type);
165: }
166: throw new ELException(LocalMessages.get("error.coerce.type",
167: value.getClass(), type));
168: }
169:
170: public static final String coerceToString(Object value) {
171: if (value == null) {
172: return "";
173: }
174: if (value instanceof String) {
175: return (String) value;
176: }
177: if (value instanceof Enum) {
178: return ((Enum) value).name();
179: }
180: return value.toString();
181: }
182:
183: @SuppressWarnings("unchecked")
184: public static final <T extends Enum<T>> T coerceToEnum(
185: Object value, Class<T> type) {
186: if (value == null || "".equals(value)) {
187: return null;
188: }
189: if (type.isInstance(value)) {
190: return (T) value;
191: }
192: if (value instanceof String) {
193: try {
194: return Enum.valueOf(type, (String) value);
195: } catch (IllegalArgumentException e) {
196: throw new ELException(LocalMessages.get(
197: "error.coerce.value", value, type));
198: }
199: }
200: throw new ELException(LocalMessages.get("error.coerce.type",
201: value.getClass(), type));
202: }
203:
204: private static final Object coerceStringToType(String value,
205: Class<?> type) {
206: PropertyEditor editor = PropertyEditorManager.findEditor(type);
207: if (editor == null) {
208: if ("".equals(value)) {
209: return null;
210: }
211: throw new ELException(LocalMessages.get(
212: "error.coerce.type", String.class, type));
213: } else {
214: if ("".equals(value)) {
215: try {
216: editor.setAsText(value);
217: } catch (IllegalArgumentException e) {
218: return null;
219: }
220: } else {
221: try {
222: editor.setAsText(value);
223: } catch (IllegalArgumentException e) {
224: throw new ELException(LocalMessages.get(
225: "error.coerce.value", value, type));
226: }
227: }
228: return editor.getValue();
229: }
230: }
231:
232: @SuppressWarnings("unchecked")
233: public static final Object coerceToType(Object value, Class<?> type) {
234: if (type == String.class) {
235: return coerceToString(value);
236: }
237: if (type.isPrimitive()) {
238: type = WRAPPER_TYPES.get(type);
239: }
240: if (Number.class.isAssignableFrom(type)) {
241: return coerceToNumber(value, (Class<? extends Number>) type);
242: }
243: if (type == Character.class) {
244: return coerceToCharacter(value);
245: }
246: if (type == Boolean.class) {
247: return coerceToBoolean(value);
248: }
249: if (Enum.class.isAssignableFrom(type)) {
250: return coerceToEnum(value, (Class<? extends Enum>) type);
251: }
252: if (value == null) {
253: return null;
254: }
255: if (type.isInstance(value)) {
256: return value;
257: }
258: if (value instanceof String) {
259: return coerceStringToType((String) value, type);
260: }
261: throw new ELException(LocalMessages.get("error.coerce.type",
262: value.getClass(), type));
263: }
264: }
|