| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.myfaces.test.el; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import javax.el.ELContext; |
| import javax.el.ExpressionFactory; |
| import javax.el.MethodExpression; |
| import javax.el.ValueExpression; |
| |
| /** |
| * <p>Mock implementation of <code>ExpressionFactory</code>.</p> |
| * |
| * @since 1.0.4 |
| */ |
| public class MockExpressionFactory extends ExpressionFactory { |
| |
| |
| // ------------------------------------------------------------ Constructors |
| |
| |
| /** Creates a new instance of MockExpressionFactory */ |
| public MockExpressionFactory() { |
| } |
| |
| |
| // ------------------------------------------------------ Instance Variables |
| |
| |
| /** |
| * <p>Literal numeric value for zero.</p> |
| */ |
| private static final Integer ZERO = new Integer(0); |
| |
| |
| // ----------------------------------------------------- Mock Object Methods |
| |
| |
| |
| // ----------------------------------------------- ExpressionFactory Methods |
| |
| |
| /** {@inheritDoc} */ |
| public Object coerceToType(Object object, Class targetType) { |
| |
| // Check for no conversion necessary |
| if ((targetType == null) || Object.class.equals(targetType)) { |
| return object; |
| } |
| |
| // Coerce to String if appropriate |
| if (String.class.equals(targetType)) { |
| if (object == null) { |
| return ""; |
| } else if (object instanceof String) { |
| return (String) object; |
| } else { |
| return object.toString(); |
| } |
| } |
| |
| // Coerce to Number (or a subclass of Number) if appropriate |
| if (isNumeric(targetType)) { |
| if (object == null) { |
| return coerce(ZERO, targetType); |
| } else if ("".equals(object)) { |
| return coerce(ZERO, targetType); |
| } else if (object instanceof String) { |
| return coerce((String) object, targetType); |
| } else if (isNumeric(object.getClass())) { |
| return coerce((Number) object, targetType); |
| } |
| throw new IllegalArgumentException("Cannot convert " + object + " to Number"); |
| } |
| |
| // Coerce to Boolean if appropriate |
| if (Boolean.class.equals(targetType) || (Boolean.TYPE == targetType)) { |
| if (object == null) { |
| return Boolean.FALSE; |
| } else if ("".equals(object)) { |
| return Boolean.FALSE; |
| } else if ((object instanceof Boolean) || (object.getClass() == Boolean.TYPE)) { |
| return (Boolean) object; |
| } else if (object instanceof String) { |
| return Boolean.valueOf((String) object); |
| } |
| throw new IllegalArgumentException("Cannot convert " + object + " to Boolean"); |
| } |
| |
| // Coerce to Character if appropriate |
| if (Character.class.equals(targetType) || (Character.TYPE == targetType)) { |
| if (object == null) { |
| return new Character((char) 0); |
| } else if ("".equals(object)) { |
| return new Character((char) 0); |
| } else if (object instanceof String) { |
| return new Character(((String) object).charAt(0)); |
| } else if (isNumeric(object.getClass())) { |
| return new Character((char) ((Number) object).shortValue()); |
| } else if ((object instanceof Character) || (object.getClass() == Character.TYPE)) { |
| return (Character) object; |
| } |
| throw new IllegalArgumentException("Cannot convert " + object + " to Character"); |
| } |
| |
| // Is the specified value type-compatible already? |
| if ((object != null) && targetType.isAssignableFrom(object.getClass())) { |
| return object; |
| } |
| |
| // We do not know how to perform this conversion |
| throw new IllegalArgumentException("Cannot convert " + object + " to " + targetType.getName()); |
| |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public MethodExpression createMethodExpression(ELContext context, |
| String expression, |
| Class expectedType, |
| Class[] signature) { |
| |
| return new MockMethodExpression(expression, signature, expectedType); |
| |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public ValueExpression createValueExpression(ELContext context, |
| String expression, |
| Class expectedType) { |
| |
| return new MockValueExpression(expression, expectedType); |
| |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public ValueExpression createValueExpression(Object instance, |
| Class expectedType) { |
| |
| return new MockVariableValueExpression(instance, expectedType); |
| |
| } |
| |
| |
| // --------------------------------------------------------- Private Methods |
| |
| |
| /** |
| * <p>Coerce the specified value to the specified Number subclass.</p> |
| * |
| * @param value Value to be coerced |
| * @param type Destination type |
| */ |
| private Number coerce(Number value, Class type) { |
| |
| if ((type == Byte.TYPE) || (type == Byte.class)) { |
| return new Byte(value.byteValue()); |
| } else if ((type == Double.TYPE) || (type == Double.class)) { |
| return new Double(value.doubleValue()); |
| } else if ((type == Float.TYPE) || (type == Float.class)) { |
| return new Float(value.floatValue()); |
| } else if ((type == Integer.TYPE) || (type == Integer.class)) { |
| return new Integer(value.intValue()); |
| } else if ((type == Long.TYPE) || (type == Long.class)) { |
| return new Long(value.longValue()); |
| } else if ((type == Short.TYPE) || (type == Short.class)) { |
| return new Short(value.shortValue()); |
| } else if (type == BigDecimal.class) { |
| if (value instanceof BigDecimal) { |
| return (BigDecimal) value; |
| } else if (value instanceof BigInteger) { |
| return new BigDecimal((BigInteger) value); |
| } else { |
| return new BigDecimal(((Number) value).doubleValue()); |
| } |
| } else if (type == BigInteger.class) { |
| if (value instanceof BigInteger) { |
| return (BigInteger) value; |
| } else if (value instanceof BigDecimal) { |
| return ((BigDecimal) value).toBigInteger(); |
| } else { |
| return BigInteger.valueOf(((Number) value).longValue()); |
| } |
| } |
| throw new IllegalArgumentException("Cannot convert " + value + " to " + type.getName()); |
| |
| } |
| |
| |
| /** |
| * <p>Coerce the specified value to the specified Number subclass.</p> |
| * |
| * @param value Value to be coerced |
| * @param type Destination type |
| */ |
| private Number coerce(String value, Class type) { |
| |
| if ((type == Byte.TYPE) || (type == Byte.class)) { |
| return Byte.valueOf(value); |
| } else if ((type == Double.TYPE) || (type == Double.class)) { |
| return Double.valueOf(value); |
| } else if ((type == Float.TYPE) || (type == Float.class)) { |
| return Float.valueOf(value); |
| } else if ((type == Integer.TYPE) || (type == Integer.class)) { |
| return Integer.valueOf(value); |
| } else if ((type == Long.TYPE) || (type == Long.class)) { |
| return Long.valueOf(value); |
| } else if ((type == Short.TYPE) || (type == Short.class)) { |
| return Short.valueOf(value); |
| } else if (type == BigDecimal.class) { |
| return new BigDecimal(value); |
| } else if (type == BigInteger.class) { |
| return new BigInteger(value); |
| } |
| throw new IllegalArgumentException("Cannot convert " + value + " to " + type.getName()); |
| |
| } |
| |
| |
| /** |
| * <p>Return <code>true</code> if the specified type is numeric.</p> |
| * |
| * @param type Type to check |
| */ |
| private boolean isNumeric(Class type) { |
| |
| return |
| (type == Byte.TYPE) || (type == Byte.class) |
| || (type == Double.TYPE) || (type == Double.class) |
| || (type == Float.TYPE) || (type == Float.class) |
| || (type == Integer.TYPE) || (type == Integer.class) |
| || (type == Long.TYPE) || (type == Long.class) |
| || (type == Short.TYPE) || (type == Short.class) |
| || (type == BigDecimal.class) || (type == BigInteger.class); |
| |
| } |
| |
| |
| } |