2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.test.el;
19  
20  import java.math.BigDecimal;
21  import java.math.BigInteger;
22  import javax.el.ELContext;
23  import javax.el.ExpressionFactory;
24  import javax.el.MethodExpression;
25  import javax.el.ValueExpression;
26  
27  /***
28   * <p>Mock implementation of <code>ExpressionFactory</code>.</p>
29   *
30   * @since 1.0.4
31   */
32  public class MockExpressionFactory extends ExpressionFactory {
33      
34  
35      // ------------------------------------------------------------ Constructors
36  
37  
38      /*** Creates a new instance of MockExpressionFactory */
39      public MockExpressionFactory() {
40      }
41      
42  
43      // ------------------------------------------------------ Instance Variables
44  
45  
46      /***
47       * <p>Literal numeric value for zero.</p>
48       */
49      private static final Integer ZERO = new Integer(0);
50  
51  
52      // ----------------------------------------------------- Mock Object Methods
53  
54  
55  
56      // ----------------------------------------------- ExpressionFactory Methods
57  
58  
59      /*** {@inheritDoc} */
60      public Object coerceToType(Object object, Class targetType) {
61  
62          // Check for no conversion necessary
63          if ((targetType == null) || Object.class.equals(targetType)) {
64              return object;
65          }
66  
67          // Coerce to String if appropriate
68          if (String.class.equals(targetType)) {
69              if (object == null) {
70                  return "";
71              } else if (object instanceof String) {
72                  return (String) object;
73              } else {
74                  return object.toString();
75              }
76          }
77  
78          // Coerce to Number (or a subclass of Number) if appropriate
79          if (isNumeric(targetType)) {
80              if (object == null) {
81                  return coerce(ZERO, targetType);
82              } else if ("".equals(object)) {
83                  return coerce(ZERO, targetType);
84              } else if (object instanceof String) {
85                  return coerce((String) object, targetType);
86              } else if (isNumeric(object.getClass())) {
87                  return coerce((Number) object, targetType);
88              }
89              throw new IllegalArgumentException("Cannot convert " + object + " to Number");
90          }
91  
92          // Coerce to Boolean if appropriate
93          if (Boolean.class.equals(targetType) || (Boolean.TYPE == targetType)) {
94              if (object == null) {
95                  return Boolean.FALSE;
96              } else if ("".equals(object)) {
97                  return Boolean.FALSE;
98              } else if ((object instanceof Boolean) || (object.getClass() == Boolean.TYPE)) {
99                  return (Boolean) object;
100             } else if (object instanceof String) {
101                 return Boolean.valueOf((String) object);
102             }
103             throw new IllegalArgumentException("Cannot convert " + object + " to Boolean");
104         }
105 
106         // Coerce to Character if appropriate
107         if (Character.class.equals(targetType) || (Character.TYPE == targetType)) {
108             if (object == null) {
109                 return new Character((char) 0);
110             } else if ("".equals(object)) {
111                 return new Character((char) 0);
112             } else if (object instanceof String) {
113                 return new Character(((String) object).charAt(0));
114             } else if (isNumeric(object.getClass())) {
115                 return new Character((char) ((Number) object).shortValue());
116             } else if ((object instanceof Character) || (object.getClass() == Character.TYPE)) {
117                 return (Character) object;
118             }
119             throw new IllegalArgumentException("Cannot convert " + object + " to Character");
120         }
121 
122         // Is the specified value type-compatible already?
123         if ((object != null) && targetType.isAssignableFrom(object.getClass())) {
124             return object;
125         }
126 
127         // We do not know how to perform this conversion
128         throw new IllegalArgumentException("Cannot convert " + object + " to " + targetType.getName());
129 
130     }
131 
132 
133     /*** {@inheritDoc} */
134     public MethodExpression createMethodExpression(ELContext context,
135                                                    String expression,
136                                                    Class expectedType,
137                                                    Class[] signature) {
138 
139         return new MockMethodExpression(expression, signature, expectedType);
140 
141     }
142 
143 
144     /*** {@inheritDoc} */
145     public ValueExpression createValueExpression(ELContext context,
146                                                  String expression,
147                                                  Class expectedType) {
148 
149         return new MockValueExpression(expression, expectedType);
150 
151     }
152 
153 
154     /*** {@inheritDoc} */
155     public ValueExpression createValueExpression(Object instance,
156                                                  Class expectedType) {
157 
158         return new MockVariableValueExpression(instance, expectedType);
159 
160     }
161 
162 
163     // --------------------------------------------------------- Private Methods
164 
165 
166     /***
167      * <p>Coerce the specified value to the specified Number subclass.</p>
168      *
169      * @param value Value to be coerced
170      * @param type Destination type
171      */
172     private Number coerce(Number value, Class type) {
173 
174         if ((type == Byte.TYPE) || (type == Byte.class)) {
175             return new Byte(value.byteValue());
176         } else if ((type == Double.TYPE) || (type == Double.class)) {
177             return new Double(value.doubleValue());
178         } else if ((type == Float.TYPE) || (type == Float.class)) {
179             return new Float(value.floatValue());
180         } else if ((type == Integer.TYPE) || (type == Integer.class)) {
181             return new Integer(value.intValue());
182         } else if ((type == Long.TYPE) || (type == Long.class)) {
183             return new Long(value.longValue());
184         } else if ((type == Short.TYPE) || (type == Short.class)) {
185             return new Short(value.shortValue());
186         } else if (type == BigDecimal.class) {
187             if (value instanceof BigDecimal) {
188                 return (BigDecimal) value;
189             } else if (value instanceof BigInteger) {
190                 return new BigDecimal((BigInteger) value);
191             } else {
192                 return new BigDecimal(((Number) value).doubleValue());
193             }
194         } else if (type == BigInteger.class) {
195             if (value instanceof BigInteger) {
196                 return (BigInteger) value;
197             } else if (value instanceof BigDecimal) {
198                 return ((BigDecimal) value).toBigInteger();
199             } else {
200                 return BigInteger.valueOf(((Number) value).longValue());
201             }
202         }
203         throw new IllegalArgumentException("Cannot convert " + value + " to " + type.getName());
204 
205     }
206 
207 
208     /***
209      * <p>Coerce the specified value to the specified Number subclass.</p>
210      *
211      * @param value Value to be coerced
212      * @param type Destination type
213      */
214     private Number coerce(String value, Class type) {
215 
216         if ((type == Byte.TYPE) || (type == Byte.class)) {
217             return Byte.valueOf(value);
218         } else if ((type == Double.TYPE) || (type == Double.class)) {
219             return Double.valueOf(value);
220         } else if ((type == Float.TYPE) || (type == Float.class)) {
221             return Float.valueOf(value);
222         } else if ((type == Integer.TYPE) || (type == Integer.class)) {
223             return Integer.valueOf(value);
224         } else if ((type == Long.TYPE) || (type == Long.class)) {
225             return Long.valueOf(value);
226         } else if ((type == Short.TYPE) || (type == Short.class)) {
227             return Short.valueOf(value);
228         } else if (type == BigDecimal.class) {
229             return new BigDecimal(value);
230         } else if (type == BigInteger.class) {
231             return new BigInteger(value);
232         }
233         throw new IllegalArgumentException("Cannot convert " + value + " to " + type.getName());
234 
235     }
236 
237 
238     /***
239      * <p>Return <code>true</code> if the specified type is numeric.</p>
240      *
241      * @param type Type to check
242      */
243     private boolean isNumeric(Class type) {
244 
245         return
246                (type == Byte.TYPE) || (type == Byte.class)
247             || (type == Double.TYPE) || (type == Double.class)
248             || (type == Float.TYPE) || (type == Float.class)
249             || (type == Integer.TYPE) || (type == Integer.class)
250             || (type == Long.TYPE) || (type == Long.class)
251             || (type == Short.TYPE) || (type == Short.class)
252             || (type == BigDecimal.class) || (type == BigInteger.class);
253 
254     }
255 
256 
257 }