001: package org.drools.rule.builder.dialect.mvel;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.util.ArrayList;
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027:
028: import org.antlr.runtime.RecognitionException;
029: import org.drools.rule.builder.RuleBuildContext;
030: import org.mvel.ExpressionCompiler;
031: import org.mvel.ParserContext;
032: import org.mvel.integration.impl.MapVariableResolver;
033:
034: /**
035: * Expression analyzer.
036: *
037: */
038: public class MVELExprAnalyzer {
039:
040: public MVELExprAnalyzer() {
041: // intentionally left blank.
042: }
043:
044: // ------------------------------------------------------------
045: // Instance methods
046: // ------------------------------------------------------------
047:
048: /**
049: * Analyze an expression.
050: *
051: * @param expr
052: * The expression to analyze.
053: * @param availDecls
054: * Total set of declarations available.
055: *
056: * @return The <code>Set</code> of declarations used by the expression.
057: * @throws RecognitionException
058: * If an error occurs in the parser.
059: */
060: public MVELAnalysisResult analyzeExpression(
061: final RuleBuildContext context, final String expr,
062: final Set[] availableIdentifiers, final Map localTypes)
063: throws RecognitionException {
064: MVELAnalysisResult result = null;
065: if (expr.trim().length() > 0) {
066: ExpressionCompiler compiler = new ExpressionCompiler(expr);
067:
068: MVELDialect dialect = (MVELDialect) context
069: .getDialect("mvel");
070:
071: final ParserContext parserContext = new ParserContext(
072: dialect.getImports(), null, context.getPkg()
073: .getName()
074: + "."
075: + context.getRuleDescr().getClassName());
076:
077: for (Iterator it = dialect.getPackgeImports().values()
078: .iterator(); it.hasNext();) {
079: String packageImport = (String) it.next();
080: parserContext.addPackageImport(packageImport);
081: }
082:
083: parserContext.setStrictTypeEnforcement(false);
084:
085: parserContext.setInterceptors(dialect.getInterceptors());
086:
087: compiler.compile(parserContext);
088:
089: result = analyze(compiler.getParserContextState()
090: .getInputs().keySet(), availableIdentifiers);
091:
092: result.setMvelVariables(compiler.getParserContextState()
093: .getVariables());
094: } else {
095: result = analyze(Collections.EMPTY_SET,
096: availableIdentifiers);
097: result.setMvelVariables(new HashMap());
098:
099: }
100: return result;
101: }
102:
103: /**
104: * Analyze an expression.
105: *
106: * @param availDecls
107: * Total set of declarations available.
108: * @param ast
109: * The AST for the expression.
110: *
111: * @return The <code>Set</code> of declarations used by the expression.
112: *
113: * @throws RecognitionException
114: * If an error occurs in the parser.
115: */
116: private MVELAnalysisResult analyze(final Set identifiers,
117: final Set[] availableIdentifiers)
118: throws RecognitionException {
119:
120: MVELAnalysisResult result = new MVELAnalysisResult();
121: result.setIdentifiers(new ArrayList(identifiers));
122:
123: final Set notBound = new HashSet(identifiers);
124: final List[] used = new List[availableIdentifiers.length];
125: for (int i = 0, length = used.length; i < length; i++) {
126: used[i] = new ArrayList();
127: }
128:
129: for (int i = 0, length = availableIdentifiers.length; i < length; i++) {
130: final Set set = availableIdentifiers[i];
131: for (final Iterator it = set.iterator(); it.hasNext();) {
132: final String eachDecl = (String) it.next();
133: if (identifiers.contains(eachDecl)) {
134: used[i].add(eachDecl);
135: notBound.remove(eachDecl);
136: }
137: }
138: }
139: result.setBoundIdentifiers(used);
140: result.setNotBoundedIdentifiers(new ArrayList(notBound));
141:
142: return result;
143: }
144: }
|