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.tree.impl.ast;
017:
018: import java.lang.reflect.InvocationTargetException;
019: import java.lang.reflect.Method;
020: import java.util.Arrays;
021:
022: import javax.el.ELContext;
023: import javax.el.ELException;
024: import javax.el.MethodInfo;
025: import javax.el.MethodNotFoundException;
026: import javax.el.PropertyNotFoundException;
027: import javax.el.ValueExpression;
028:
029: import de.odysseus.el.misc.LocalMessages;
030: import de.odysseus.el.tree.Bindings;
031: import de.odysseus.el.tree.IdentifierNode;
032:
033: public final class AstIdentifier extends AstNode implements
034: IdentifierNode {
035: private final String name;
036: private final int index;
037:
038: public AstIdentifier(String name, int index) {
039: this .name = name;
040: this .index = index;
041: }
042:
043: public Class<?> getType(Bindings bindings, ELContext context) {
044: ValueExpression expression = bindings.getVariable(index);
045: if (expression != null) {
046: return expression.getType(context);
047: }
048: Class result = context.getELResolver().getType(context, null,
049: name);
050: if (!context.isPropertyResolved()) {
051: throw new PropertyNotFoundException(LocalMessages.get(
052: "error.identifier.property.notfound", name));
053: }
054: return result;
055: }
056:
057: public boolean isLeftValue() {
058: return true;
059: }
060:
061: public boolean isLiteralText() {
062: return false;
063: }
064:
065: @Override
066: public Object eval(Bindings bindings, ELContext context) {
067: ValueExpression expression = bindings.getVariable(index);
068: if (expression != null) {
069: return expression.getValue(context);
070: }
071: Object result = context.getELResolver().getValue(context, null,
072: name);
073: if (!context.isPropertyResolved()) {
074: throw new PropertyNotFoundException(LocalMessages.get(
075: "error.identifier.property.notfound", name));
076: }
077: return result;
078: }
079:
080: public void setValue(Bindings bindings, ELContext context,
081: Object value) {
082: ValueExpression expression = bindings.getVariable(index);
083: if (expression != null) {
084: expression.setValue(context, value);
085: }
086: context.getELResolver().setValue(context, null, name, value);
087: if (!context.isPropertyResolved()) {
088: throw new PropertyNotFoundException(LocalMessages.get(
089: "error.identifier.property.notfound", name));
090: }
091: }
092:
093: public boolean isReadOnly(Bindings bindings, ELContext context) {
094: ValueExpression expression = bindings.getVariable(index);
095: if (expression != null) {
096: return expression.isReadOnly(context);
097: }
098: boolean result = context.getELResolver().isReadOnly(context,
099: null, name);
100: if (!context.isPropertyResolved()) {
101: throw new PropertyNotFoundException(LocalMessages.get(
102: "error.identifier.property.notfound", name));
103: }
104: return result;
105: }
106:
107: private Method getMethod(Bindings bindings, ELContext context,
108: Class<?> returnType, Class<?>[] paramTypes) {
109: Object value = eval(bindings, context);
110: if (value == null) {
111: throw new MethodNotFoundException(LocalMessages.get(
112: "error.identifier.method.notfound", name));
113: }
114: if (value instanceof Method) {
115: Method method = (Method) value;
116: if (returnType != null
117: && !returnType.isAssignableFrom(method
118: .getReturnType())) {
119: throw new MethodNotFoundException(LocalMessages.get(
120: "error.identifier.method.notfound", name));
121: }
122: if (!Arrays.equals(method.getParameterTypes(), paramTypes)) {
123: throw new MethodNotFoundException(LocalMessages.get(
124: "error.identifier.method.notfound", name));
125: }
126: return method;
127: }
128: throw new MethodNotFoundException(LocalMessages.get(
129: "error.identifier.method.notamethod", name, value
130: .getClass()));
131: }
132:
133: public MethodInfo getMethodInfo(Bindings bindings,
134: ELContext context, Class<?> returnType,
135: Class<?>[] paramTypes) {
136: Method method = getMethod(bindings, context, returnType,
137: paramTypes);
138: return new MethodInfo(method.getName(), method.getReturnType(),
139: paramTypes);
140: }
141:
142: public Object invoke(Bindings bindings, ELContext context,
143: Class<?> returnType, Class<?>[] paramTypes, Object[] params) {
144: Method method = getMethod(bindings, context, returnType,
145: paramTypes);
146: try {
147: return method.invoke(null, params);
148: } catch (IllegalAccessException e) {
149: throw new ELException(LocalMessages.get(
150: "error.identifier.method.access", name));
151: } catch (IllegalArgumentException e) {
152: throw new ELException(LocalMessages.get(
153: "error.identifier.method.invocation", name, e));
154: } catch (InvocationTargetException e) {
155: throw new ELException(LocalMessages.get(
156: "error.identifier.method.invocation", name, e
157: .getCause()));
158: }
159: }
160:
161: @Override
162: public String toString() {
163: return name;
164: }
165:
166: @Override
167: public void appendStructure(StringBuilder b, Bindings bindings) {
168: ValueExpression expression = bindings == null ? null : bindings
169: .getVariable(index);
170: b.append(expression != null ? "<var>" : name);
171: }
172:
173: public int getIndex() {
174: return index;
175: }
176:
177: public String getName() {
178: return name;
179: }
180:
181: public int getCardinality() {
182: return 0;
183: }
184:
185: public AstNode getChild(int i) {
186: return null;
187: }
188: }
|