001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: */
055:
056: package org.jbpm.jpdl.el.impl;
057:
058: import java.lang.reflect.Array;
059: import java.lang.reflect.InvocationTargetException;
060: import java.util.List;
061: import java.util.Map;
062:
063: import org.jbpm.jpdl.el.ELException;
064: import org.jbpm.jpdl.el.FunctionMapper;
065: import org.jbpm.jpdl.el.VariableResolver;
066:
067: /**
068: *
069: * <p>
070: * Represents an operator that obtains a Map entry, an indexed value, a property
071: * value, or an indexed property value of an object. The following are the rules
072: * for evaluating this operator:
073: *
074: * <ul>
075: *
076: * <pre>
077: * Evaluating a[b] (assuming a.b == a["b"])
078: * a is null
079: * return null
080: * b is null
081: * return null
082: * a is Map
083: * !a.containsKey (b)
084: * return null
085: * a.get(b) == null
086: * return null
087: * otherwise
088: * return a.get(b)
089: * a is List or array
090: * coerce b to int (using coercion rules)
091: * coercion couldn't be performed
092: * error
093: * a.get(b) or Array.get(a, b) throws ArrayIndexOutOfBoundsException or IndexOutOfBoundsException
094: * return null
095: * a.get(b) or Array.get(a, b) throws other exception
096: * error
097: * return a.get(b) or Array.get(a, b)
098: *
099: * coerce b to String
100: * b is a readable property of a
101: * getter throws an exception
102: * error
103: * otherwise
104: * return result of getter call
105: *
106: * otherwise
107: * error
108: * </pre>
109: *
110: * </ul>
111: *
112: * @author Nathan Abramson - Art Technology Group
113: * @author Shawn Bayern
114: * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author$
115: */
116:
117: public class ArraySuffix extends ValueSuffix {
118:
119: // -------------------------------------
120: // Constants
121: // -------------------------------------
122:
123: // Zero-argument array
124: static Object[] sNoArgs = new Object[0];
125:
126: // -------------------------------------
127: // Properties
128: // -------------------------------------
129: // property index
130:
131: Expression mIndex;
132:
133: public Expression getIndex() {
134: return mIndex;
135: }
136:
137: public void setIndex(Expression pIndex) {
138: mIndex = pIndex;
139: }
140:
141: // -------------------------------------
142: /**
143: *
144: * Constructor
145: */
146: public ArraySuffix(Expression pIndex) {
147: mIndex = pIndex;
148: }
149:
150: // -------------------------------------
151: /**
152: *
153: * Gets the value of the index
154: */
155: Object evaluateIndex(VariableResolver pResolver,
156: FunctionMapper functions, Logger pLogger)
157: throws ELException {
158: return mIndex.evaluate(pResolver, functions, pLogger);
159: }
160:
161: // -------------------------------------
162: /**
163: *
164: * Returns the operator symbol
165: */
166: String getOperatorSymbol() {
167: return "[]";
168: }
169:
170: // -------------------------------------
171: // ValueSuffix methods
172: // -------------------------------------
173: /**
174: *
175: * Returns the expression in the expression language syntax
176: */
177: public String getExpressionString() {
178: return "[" + mIndex.getExpressionString() + "]";
179: }
180:
181: // -------------------------------------
182: /**
183: *
184: * Evaluates the expression in the given context, operating on the given
185: * value.
186: */
187: public Object evaluate(Object pValue, VariableResolver pResolver,
188: FunctionMapper functions, Logger pLogger)
189: throws ELException {
190: Object indexVal;
191: String indexStr;
192: BeanInfoProperty beanInfoProperty;
193: BeanMethod beanMethod;
194:
195: // Check for null value
196: if (pValue == null) {
197: if (pLogger.isLoggingWarning()) {
198: pLogger.logWarning(
199: Constants.CANT_GET_INDEXED_VALUE_OF_NULL,
200: getOperatorSymbol());
201: }
202: return null;
203: }
204:
205: // Evaluate the index
206: else if ((indexVal = evaluateIndex(pResolver, functions,
207: pLogger)) == null) {
208: if (pLogger.isLoggingWarning()) {
209: pLogger.logWarning(Constants.CANT_GET_NULL_INDEX,
210: getOperatorSymbol());
211: }
212: return null;
213: }
214:
215: // See if it's a Map
216: else if (pValue instanceof Map) {
217: Map val = (Map) pValue;
218: return val.get(indexVal);
219: }
220:
221: // See if it's a List or array
222: else if (pValue instanceof List || pValue.getClass().isArray()) {
223: Integer indexObj = Coercions.coerceToInteger(indexVal,
224: pLogger);
225: if (indexObj == null) {
226: if (pLogger.isLoggingError()) {
227: pLogger.logError(Constants.BAD_INDEX_VALUE,
228: getOperatorSymbol(), indexVal.getClass()
229: .getName());
230: }
231: return null;
232: } else if (pValue instanceof List) {
233: try {
234: return ((List) pValue).get(indexObj.intValue());
235: } catch (ArrayIndexOutOfBoundsException exc) {
236: if (pLogger.isLoggingWarning()) {
237: pLogger.logWarning(
238: Constants.EXCEPTION_ACCESSING_LIST,
239: exc, indexObj);
240: }
241: return null;
242: } catch (IndexOutOfBoundsException exc) {
243: if (pLogger.isLoggingWarning()) {
244: pLogger.logWarning(
245: Constants.EXCEPTION_ACCESSING_LIST,
246: exc, indexObj);
247: }
248: return null;
249: } catch (Exception exc) {
250: if (pLogger.isLoggingError()) {
251: pLogger.logError(
252: Constants.EXCEPTION_ACCESSING_LIST,
253: exc, indexObj);
254: }
255: return null;
256: }
257: } else {
258: try {
259: return Array.get(pValue, indexObj.intValue());
260: } catch (ArrayIndexOutOfBoundsException exc) {
261: if (pLogger.isLoggingWarning()) {
262: pLogger.logWarning(
263: Constants.EXCEPTION_ACCESSING_ARRAY,
264: exc, indexObj);
265: }
266: return null;
267: } catch (IndexOutOfBoundsException exc) {
268: if (pLogger.isLoggingWarning()) {
269: pLogger.logWarning(
270: Constants.EXCEPTION_ACCESSING_ARRAY,
271: exc, indexObj);
272: }
273: return null;
274: } catch (Exception exc) {
275: if (pLogger.isLoggingError()) {
276: pLogger.logError(
277: Constants.EXCEPTION_ACCESSING_ARRAY,
278: exc, indexObj);
279: }
280: return null;
281: }
282: }
283: }
284:
285: // Coerce to a String for property access
286:
287: else if ((indexStr = Coercions
288: .coerceToString(indexVal, pLogger)) == null) {
289: return null;
290: }
291:
292: // Look for a JavaBean property
293: else if ((beanInfoProperty = BeanInfoManager
294: .getBeanInfoProperty(pValue.getClass(), indexStr,
295: pLogger)) != null
296: && beanInfoProperty.getReadMethod() != null) {
297: try {
298: return beanInfoProperty.getReadMethod().invoke(pValue,
299: sNoArgs);
300: } catch (InvocationTargetException exc) {
301: if (pLogger.isLoggingError()) {
302: pLogger.logError(Constants.ERROR_GETTING_PROPERTY,
303: exc.getTargetException(), indexStr, pValue
304: .getClass().getName());
305: }
306: return null;
307: } catch (Exception exc) {
308: if (pLogger.isLoggingError()) {
309: pLogger.logError(Constants.ERROR_GETTING_PROPERTY,
310: exc, indexStr, pValue.getClass().getName());
311: }
312: return null;
313: }
314: }
315:
316: // Look for a JavaBean method
317: else if ((beanMethod = BeanInfoManager.getBeanMethod(pValue
318: .getClass(), indexStr, pLogger)) != null) {
319: try {
320: return beanMethod.invoke(pValue);
321: } catch (InvocationTargetException exc) {
322: if (pLogger.isLoggingError()) {
323: pLogger.logError(Constants.ERROR_INVOKING_METHOD,
324: exc.getTargetException(), indexStr, pValue
325: .getClass().getName());
326: }
327: return null;
328: } catch (Exception exc) {
329: if (pLogger.isLoggingError()) {
330: pLogger.logError(Constants.ERROR_INVOKING_METHOD,
331: exc, indexStr, pValue.getClass().getName());
332: }
333: return null;
334: }
335: }
336:
337: else {
338: if (pLogger.isLoggingError()) {
339: pLogger.logError(Constants.CANT_FIND_INDEX, indexVal,
340: pValue.getClass().getName(),
341: getOperatorSymbol());
342: }
343: return null;
344: }
345: }
346:
347: // -------------------------------------
348: }
|