001: /*
002: * Copyright 2007 JBoss Inc
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:
017: package org.drools.rule.builder.dialect.mvel;
018:
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import org.drools.base.accumulators.AccumulateFunction;
024: import org.drools.base.accumulators.MVELAccumulatorFunctionExecutor;
025: import org.drools.base.mvel.DroolsMVELFactory;
026: import org.drools.base.mvel.MVELAccumulator;
027: import org.drools.compiler.Dialect;
028: import org.drools.lang.descr.AccumulateDescr;
029: import org.drools.lang.descr.BaseDescr;
030: import org.drools.lang.descr.PatternDescr;
031: import org.drools.rule.Accumulate;
032: import org.drools.rule.Declaration;
033: import org.drools.rule.Pattern;
034: import org.drools.rule.RuleConditionElement;
035: import org.drools.rule.builder.AccumulateBuilder;
036: import org.drools.rule.builder.PatternBuilder;
037: import org.drools.rule.builder.RuleBuildContext;
038: import org.drools.spi.Accumulator;
039: import org.mvel.MVEL;
040:
041: /**
042: * A builder for the java dialect accumulate version
043: *
044: * @author etirelli
045: */
046: public class MVELAccumulateBuilder implements AccumulateBuilder {
047:
048: public RuleConditionElement build(final RuleBuildContext context,
049: final BaseDescr descr) {
050: return build(context, descr, null);
051: }
052:
053: public RuleConditionElement build(final RuleBuildContext context,
054: final BaseDescr descr, final Pattern prefixPattern) {
055:
056: final AccumulateDescr accumDescr = (AccumulateDescr) descr;
057:
058: final PatternBuilder patternBuilder = (PatternBuilder) context
059: .getDialect().getBuilder(PatternDescr.class);
060:
061: // create source pattern
062: final Pattern sourcePattern = (Pattern) patternBuilder.build(
063: context, accumDescr.getInputPattern());
064:
065: if (sourcePattern == null) {
066: return null;
067: }
068:
069: MVELDialect dialect = (MVELDialect) context.getDialect();
070:
071: final Declaration[] sourceDeclArr = (Declaration[]) sourcePattern
072: .getOuterDeclarations().values().toArray(
073: new Declaration[0]);
074:
075: final DroolsMVELFactory factory = new DroolsMVELFactory(context
076: .getDeclarationResolver().getDeclarations(),
077: sourcePattern.getOuterDeclarations(), context.getPkg()
078: .getGlobals());
079: factory.setNextFactory(dialect
080: .getStaticMethodImportResolverFactory());
081:
082: Accumulator accumulator = null;
083: Declaration[] declarations = null;
084:
085: if (accumDescr.isExternalFunction()) {
086: // build an external function executor
087: final Dialect.AnalysisResult analysis = dialect
088: .analyzeExpression(context, accumDescr, accumDescr
089: .getExpression());
090:
091: int size = analysis.getBoundIdentifiers()[0].size();
092: declarations = new Declaration[size];
093: for (int i = 0; i < size; i++) {
094: declarations[i] = context
095: .getDeclarationResolver()
096: .getDeclaration(
097: (String) analysis.getBoundIdentifiers()[0]
098: .get(i));
099: }
100:
101: final Serializable expression = dialect
102: .compile((String) accumDescr.getExpression(),
103: analysis, null, sourcePattern
104: .getOuterDeclarations(), context);
105:
106: AccumulateFunction function = context.getConfiguration()
107: .getAccumulateFunction(
108: accumDescr.getFunctionIdentifier());
109:
110: accumulator = new MVELAccumulatorFunctionExecutor(factory,
111: expression, function);
112: } else {
113: // it is a custom accumulate
114: final MVELAnalysisResult initCodeAnalysis = (MVELAnalysisResult) dialect
115: .analyzeBlock(context, accumDescr, accumDescr
116: .getInitCode());
117:
118: final MVELAnalysisResult actionCodeAnalysis = (MVELAnalysisResult) dialect
119: .analyzeBlock(context, accumDescr, null, accumDescr
120: .getActionCode(), initCodeAnalysis
121: .getMvelVariables());
122: actionCodeAnalysis.setMvelVariables(initCodeAnalysis
123: .getMvelVariables());
124: final MVELAnalysisResult resultCodeAnalysis = (MVELAnalysisResult) dialect
125: .analyzeExpression(context, accumDescr, accumDescr
126: .getResultCode(), initCodeAnalysis
127: .getMvelVariables());
128: resultCodeAnalysis.setMvelVariables(initCodeAnalysis
129: .getMvelVariables());
130:
131: final List requiredDeclarations = new ArrayList(
132: initCodeAnalysis.getBoundIdentifiers()[0]);
133: requiredDeclarations.addAll(actionCodeAnalysis
134: .getBoundIdentifiers()[0]);
135: requiredDeclarations.addAll(resultCodeAnalysis
136: .getBoundIdentifiers()[0]);
137:
138: if (accumDescr.getReverseCode() != null) {
139: final Dialect.AnalysisResult reverseCodeAnalysis = context
140: .getDialect().analyzeBlock(context, accumDescr,
141: accumDescr.getActionCode());
142: requiredDeclarations.addAll(reverseCodeAnalysis
143: .getBoundIdentifiers()[0]);
144: }
145:
146: declarations = new Declaration[requiredDeclarations.size()];
147: for (int i = 0, size = requiredDeclarations.size(); i < size; i++) {
148: declarations[i] = context.getDeclarationResolver()
149: .getDeclaration(
150: (String) requiredDeclarations.get(i));
151: }
152:
153: final Serializable init = dialect.compile(
154: (String) accumDescr.getInitCode(),
155: initCodeAnalysis, null, sourcePattern
156: .getOuterDeclarations(), context);
157: final Serializable action = dialect.compile(
158: (String) accumDescr.getActionCode(),
159: actionCodeAnalysis, null, sourcePattern
160: .getOuterDeclarations(), context);
161:
162: Serializable reverse = null;
163: if (accumDescr.getReverseCode() != null) {
164: reverse = dialect.compile((String) accumDescr
165: .getReverseCode(), resultCodeAnalysis, null,
166: sourcePattern.getOuterDeclarations(), context);
167: }
168:
169: final Serializable result = dialect.compile(
170: (String) accumDescr.getResultCode(),
171: resultCodeAnalysis, null, sourcePattern
172: .getOuterDeclarations(), context);
173:
174: accumulator = new MVELAccumulator(factory, init, action,
175: reverse, result);
176:
177: }
178:
179: final Accumulate accumulate = new Accumulate(sourcePattern,
180: declarations, sourceDeclArr, accumulator);
181: return accumulate;
182: }
183:
184: }
|