KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > el > lang > ExpressionBuilder


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.el.lang;
19
20 import java.io.StringReader JavaDoc;
21 import java.lang.ref.SoftReference JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.WeakHashMap JavaDoc;
25 import java.util.concurrent.ConcurrentHashMap JavaDoc;
26 import java.util.concurrent.ConcurrentMap JavaDoc;
27
28 import javax.el.ELContext;
29 import javax.el.ELException;
30 import javax.el.FunctionMapper;
31 import javax.el.MethodExpression;
32 import javax.el.ValueExpression;
33 import javax.el.VariableMapper;
34
35 import org.apache.el.MethodExpressionImpl;
36 import org.apache.el.MethodExpressionLiteral;
37 import org.apache.el.ValueExpressionImpl;
38 import org.apache.el.parser.AstCompositeExpression;
39 import org.apache.el.parser.AstDeferredExpression;
40 import org.apache.el.parser.AstDynamicExpression;
41 import org.apache.el.parser.AstFunction;
42 import org.apache.el.parser.AstIdentifier;
43 import org.apache.el.parser.AstLiteralExpression;
44 import org.apache.el.parser.AstValue;
45 import org.apache.el.parser.ELParser;
46 import org.apache.el.parser.Node;
47 import org.apache.el.parser.NodeVisitor;
48 import org.apache.el.parser.ParseException;
49 import org.apache.el.util.ConcurrentCache;
50 import org.apache.el.util.MessageFactory;
51
52 /**
53  * @author Jacob Hookom [jacob@hookom.net]
54  * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: markt $
55  */

56 public final class ExpressionBuilder implements NodeVisitor {
57
58     private static final ConcurrentCache cache = new ConcurrentCache(5000);
59
60     private FunctionMapper fnMapper;
61
62     private VariableMapper varMapper;
63
64     private String JavaDoc expression;
65
66     /**
67      *
68      */

69     public ExpressionBuilder(String JavaDoc expression, ELContext ctx)
70             throws ELException {
71         this.expression = expression;
72
73         FunctionMapper ctxFn = ctx.getFunctionMapper();
74         VariableMapper ctxVar = ctx.getVariableMapper();
75
76         if (ctxFn != null) {
77             this.fnMapper = new FunctionMapperFactory(ctxFn);
78         }
79         if (ctxVar != null) {
80             this.varMapper = new VariableMapperFactory(ctxVar);
81         }
82     }
83
84     public final static Node createNode(String JavaDoc expr) throws ELException {
85         Node n = createNodeInternal(expr);
86         return n;
87     }
88
89     private final static Node createNodeInternal(String JavaDoc expr)
90             throws ELException {
91         if (expr == null) {
92             throw new ELException(MessageFactory.get("error.null"));
93         }
94
95         Node n = (Node) cache.get(expr);
96         if (n == null) {
97             try {
98                 n = (new ELParser(new StringReader JavaDoc(expr)))
99                         .CompositeExpression();
100
101                 // validate composite expression
102
if (n instanceof AstCompositeExpression) {
103                     int numChildren = n.jjtGetNumChildren();
104                     if (numChildren == 1) {
105                         n = n.jjtGetChild(0);
106                     } else {
107                         Class JavaDoc type = null;
108                         Node child = null;
109                         for (int i = 0; i < numChildren; i++) {
110                             child = n.jjtGetChild(i);
111                             if (child instanceof AstLiteralExpression)
112                                 continue;
113                             if (type == null)
114                                 type = child.getClass();
115                             else {
116                                 if (!type.equals(child.getClass())) {
117                                     throw new ELException(MessageFactory.get(
118                                             "error.mixed", expr));
119                                 }
120                             }
121                         }
122                     }
123                 }
124                 if (n instanceof AstDeferredExpression
125                         || n instanceof AstDynamicExpression) {
126                     n = n.jjtGetChild(0);
127                 }
128                 cache.put(expr, n);
129             } catch (ParseException pe) {
130                 throw new ELException("Error Parsing: " + expr, pe);
131             }
132         }
133         return n;
134     }
135
136     private void prepare(Node node) throws ELException {
137         try {
138             node.accept(this);
139         } catch (Exception JavaDoc e) {
140             throw (ELException) e;
141         }
142         if (this.fnMapper instanceof FunctionMapperFactory) {
143             this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create();
144         }
145         if (this.varMapper instanceof VariableMapperFactory) {
146             this.varMapper = ((VariableMapperFactory) this.varMapper).create();
147         }
148     }
149
150     private Node build() throws ELException {
151         Node n = createNodeInternal(this.expression);
152         this.prepare(n);
153         if (n instanceof AstDeferredExpression
154                 || n instanceof AstDynamicExpression) {
155             n = n.jjtGetChild(0);
156         }
157         return n;
158     }
159
160     /*
161      * (non-Javadoc)
162      *
163      * @see com.sun.el.parser.NodeVisitor#visit(com.sun.el.parser.Node)
164      */

165     public void visit(Node node) throws ELException {
166         if (node instanceof AstFunction) {
167
168             AstFunction funcNode = (AstFunction) node;
169
170             if (this.fnMapper == null) {
171                 throw new ELException(MessageFactory.get("error.fnMapper.null"));
172             }
173             Method JavaDoc m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode
174                     .getLocalName());
175             if (m == null) {
176                 throw new ELException(MessageFactory.get(
177                         "error.fnMapper.method", funcNode.getOutputName()));
178             }
179             int pcnt = m.getParameterTypes().length;
180             if (node.jjtGetNumChildren() != pcnt) {
181                 throw new ELException(MessageFactory.get(
182                         "error.fnMapper.paramcount", funcNode.getOutputName(),
183                         "" + pcnt, "" + node.jjtGetNumChildren()));
184             }
185         } else if (node instanceof AstIdentifier && this.varMapper != null) {
186             String JavaDoc variable = ((AstIdentifier) node).getImage();
187
188             // simply capture it
189
this.varMapper.resolveVariable(variable);
190         }
191     }
192
193     public ValueExpression createValueExpression(Class JavaDoc expectedType)
194             throws ELException {
195         Node n = this.build();
196         return new ValueExpressionImpl(this.expression, n, this.fnMapper,
197                 this.varMapper, expectedType);
198     }
199
200     public MethodExpression createMethodExpression(Class JavaDoc expectedReturnType,
201             Class JavaDoc[] expectedParamTypes) throws ELException {
202         Node n = this.build();
203         if (n instanceof AstValue || n instanceof AstIdentifier) {
204             return new MethodExpressionImpl(expression, n, this.fnMapper,
205                     this.varMapper, expectedReturnType, expectedParamTypes);
206         } else if (n instanceof AstLiteralExpression) {
207             return new MethodExpressionLiteral(expression, expectedReturnType,
208                     expectedParamTypes);
209         } else {
210             throw new ELException("Not a Valid Method Expression: "
211                     + expression);
212         }
213     }
214 }
215
Popular Tags