/*
* Copyright 2006 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.rule.builder.dialect.java;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.drools.base.mvel.MVELCompilationUnit;
import org.drools.compiler.AnalysisResult;
import org.drools.compiler.BoundIdentifiers;
import org.drools.compiler.DescrBuildError;
import org.drools.core.util.ClassUtils;
import org.drools.lang.descr.RuleDescr;
import org.drools.reteoo.RuleTerminalNode.SortDeclarations;
import org.drools.rule.Declaration;
import org.drools.rule.builder.ConsequenceBuilder;
import org.drools.rule.builder.RuleBuildContext;
import org.drools.rule.builder.dialect.java.parser.JavaBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaCatchBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaContainerBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaElseBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaFinalBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaForBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaIfBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaInterfacePointsDescr;
import org.drools.rule.builder.dialect.java.parser.JavaModifyBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaThrowBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaTryBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaWhileBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaBlockDescr.BlockType;
import org.drools.rule.builder.dialect.java.parser.JavaRetractBlockDescr;
import org.drools.rule.builder.dialect.java.parser.JavaUpdateBlockDescr;
import org.drools.rule.builder.dialect.mvel.MVELAnalysisResult;
import org.drools.rule.builder.dialect.mvel.MVELConsequenceBuilder;
import org.drools.rule.builder.dialect.mvel.MVELDialect;
import org.drools.spi.KnowledgeHelper;
import org.drools.spi.PatternExtractor;
import org.mvel2.Macro;
import org.mvel2.MacroProcessor;
import org.mvel2.compiler.ExecutableStatement;
public class JavaConsequenceBuilder extends AbstractJavaRuleBuilder
implements
ConsequenceBuilder {
private final Pattern lineBreakFinder = Pattern.compile( "\\r\\n|\\r|\\n" );
/* (non-Javadoc)
* @see org.drools.semantics.java.builder.ConsequenceBuilder#buildConsequence(org.drools.semantics.java.builder.BuildContext, org.drools.semantics.java.builder.BuildUtils, org.drools.lang.descr.RuleDescr)
*/
public void build(final RuleBuildContext context, String consequenceName) {
// pushing consequence LHS into the stack for variable resolution
context.getBuildStack().push( context.getRule().getLhs() );
final String className = consequenceName + "Consequence";
final RuleDescr ruleDescr = context.getRuleDescr();
Map<String, Declaration> decls = context.getDeclarationResolver().getDeclarations( context.getRule() );
BoundIdentifiers bindings = new BoundIdentifiers(context.getDeclarationResolver().getDeclarationClasses( decls ),
context.getPackageBuilder().getGlobals(),
null,
KnowledgeHelper.class );
String consequenceStr = ( "default".equals( consequenceName ) ) ? (String) ruleDescr.getConsequence() : (String) ruleDescr.getNamedConsequences().get( consequenceName );
consequenceStr = consequenceStr + "\n";
JavaAnalysisResult analysis = ( JavaAnalysisResult) context.getDialect().analyzeBlock( context,
ruleDescr,
consequenceStr,
bindings );
if ( analysis == null ) {
// not possible to get the analysis results
return;
}
// This is a list of all the non container blocks, which initially are in tree form.
List<JavaBlockDescr> blocks = new ArrayList<JavaBlockDescr>();
buildBlockDescrs( blocks, analysis.getBlockDescrs() );
// @TODO <!--(mdp) commented this out until MVEL supports generics.
// // Set the inputs for each container, this is needed for modifes when the target context is the result of an expression
// setContainerBlockInputs(context,
// descrs,
// analysis.getBlockDescrs(),
// consequenceStr,
// bindings,
// new HashMap(),
// 0 );
// @TODO (mdp) commented this out until MVEL supports generics.-->
// this will fix modify, retract, insert, update, entrypoints and channels
String fixedConsequence = this.fixBlockDescr( context,
consequenceStr,
blocks,
bindings,
decls );
if ( fixedConsequence == null ) {
// not possible to rewrite the modify blocks
return;
}
fixedConsequence = ((JavaDialect) context.getDialect()).getKnowledgeHelperFixer().fix( fixedConsequence );
final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();
final Declaration[] declarations = new Declaration[usedIdentifiers.getDeclrClasses().size()];
String[] declrStr = new String[declarations.length];
int j = 0;
for (String str : usedIdentifiers.getDeclrClasses().keySet() ) {
declrStr[j] = str;
declarations[j++] = decls.get( str );
}
Arrays.sort( declarations, SortDeclarations.instance );
for ( int i = 0; i < declrStr.length; i++) {
declrStr[i] = declarations[i].getIdentifier();
}
context.getRule().setRequiredDeclarations( declrStr );
final Map<String, Object> map = createVariableContext( className,
fixedConsequence,
context,
declarations,
null,
usedIdentifiers.getGlobals(),
(JavaAnalysisResult) analysis );
map.put( "consequenceName", consequenceName );
//final int[] indexes = new int[declarations.length];
final Integer[] indexes = new Integer[declarations.length];
final Boolean[] notPatterns = new Boolean[declarations.length];
for ( int i = 0, length = declarations.length; i < length; i++ ) {
indexes[i] = i;
notPatterns[i] = (declarations[i].getExtractor() instanceof PatternExtractor) ? Boolean.FALSE : Boolean.TRUE ;
if ( (indexes[i]).intValue() == -1 ) {
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
ruleDescr,
null,
"Internal Error : Unable to find declaration in list while generating the consequence invoker" ) );
}
}
map.put( "indexes",
indexes );
map.put( "notPatterns",
notPatterns );
generatTemplates( "consequenceMethod",
"consequenceInvoker",
context,
className,
map,
context.getRule(),
ruleDescr );
// popping Rule.getLHS() from the build stack
context.getBuildStack().pop();
}
protected String fixBlockDescr(final RuleBuildContext context,
String originalCode,
List<JavaBlockDescr> blocks,
BoundIdentifiers bindings,
Map<String, Declaration> decls) {
MVELDialect mvel = (MVELDialect) context.getDialect( "mvel" );
// sorting exit points for correct order iteration
Collections.sort( blocks,
new Comparator<JavaBlockDescr>() {
public int compare(JavaBlockDescr o1,
JavaBlockDescr o2) {
return o1.getStart() - o2.getStart();
}
} );
StringBuilder consequence = new StringBuilder();
int lastAdded = 0;
for ( JavaBlockDescr block : blocks ) {
if ( block.getEnd() == 0 ) {
// do nothing, it was incorrectly parsed, but this error should be picked up else where
continue;
}
// adding chunk
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 ) );
lastAdded = block.getEnd();
switch ( block.getType() ) {
case MODIFY :
case UPDATE :
case RETRACT :
rewriteDescr( context,
originalCode,
mvel,
consequence,
(JavaBlockDescr) block,
bindings,
decls );
break;
case ENTRY :
case EXIT :
case CHANNEL :
rewriteInterfacePoint( context,
originalCode,
consequence,
(JavaInterfacePointsDescr) block );
break;
default:
consequence.append( originalCode.substring( block.getStart() - 1,
lastAdded ) );
}
}
consequence.append( originalCode.substring( lastAdded ) );
return consequence.toString();
}
public void buildBlockDescrs(List<JavaBlockDescr> descrs,
JavaContainerBlockDescr parentBlock) {
for ( JavaBlockDescr block : parentBlock.getJavaBlockDescrs() ) {
if( block instanceof JavaContainerBlockDescr ) {
buildBlockDescrs( descrs, (JavaContainerBlockDescr) block );
} else {
descrs.add( block );
}
}
}
/**
* This code is not currently used, it's commented out in method caller. This is because we couldn't
* get this to work and will have to wait until MVEL supports genercs (mdp).
* @param context
* @param descrs
* @param parentBlock
* @param originalCode
* @param bindings
* @param parentVars
* @param offset
*/
protected void setContainerBlockInputs(RuleBuildContext context,
List<JavaBlockDescr> descrs,
JavaContainerBlockDescr parentBlock,
String originalCode,
BoundIdentifiers bindings,
Map<String, Class<?>> parentVars,
int offset) {
StringBuilder consequence = new StringBuilder();
int lastAdded = 0;
// strip blocks, so we can analyse this block with MVEL
for ( JavaBlockDescr block : parentBlock.getJavaBlockDescrs() ) {
if ( block.getEnd() == 0 ) {
// do nothing, it was incorrectly parsed, but this error should be picked up else where
continue;
}
if ( block.getType() == BlockType.TRY ) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaTryBlockDescr tryDescr = (JavaTryBlockDescr) block;
if ( tryDescr.getFinal() != null ) {
lastAdded = tryDescr.getFinal().getEnd() - offset;
} else {
lastAdded = tryDescr.getCatches().get( tryDescr.getCatches().size()-1 ).getEnd() - offset;
}
stripTryDescr( context,
originalCode,
consequence,
(JavaTryBlockDescr) block,
offset );
} else if (block.getType() == BlockType.THROW) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaThrowBlockDescr throwBlock = (JavaThrowBlockDescr) block;
addWhiteSpaces(originalCode, consequence, throwBlock.getStart()-offset, throwBlock.getTextStart()-offset);
consequence.append( originalCode.substring( throwBlock.getTextStart()-offset-1, throwBlock.getEnd()-1-offset ) +";");
lastAdded = throwBlock.getEnd()-offset;
} else if ( block.getType() == BlockType.IF ) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaIfBlockDescr ifDescr = (JavaIfBlockDescr) block;
lastAdded = ifDescr.getEnd() - offset;
stripBlockDescr( context,
originalCode,
consequence,
ifDescr,
offset );
} else if ( block.getType() == BlockType.ELSE ) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaElseBlockDescr elseDescr = (JavaElseBlockDescr) block;
lastAdded = elseDescr.getEnd() - offset;
stripBlockDescr( context,
originalCode,
consequence,
elseDescr,
offset );
} else if ( block.getType() == BlockType.WHILE) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaWhileBlockDescr whileDescr = (JavaWhileBlockDescr) block;
lastAdded = whileDescr.getEnd() - offset;
stripBlockDescr( context,
originalCode,
consequence,
whileDescr,
offset );
} else if ( block.getType() == BlockType.FOR) {
// adding previous chunk up to the start of this block
consequence.append( originalCode.substring( lastAdded,
block.getStart() - 1 - offset ) );
JavaForBlockDescr forDescr = (JavaForBlockDescr) block;
lastAdded = forDescr.getEnd() - offset;
stripBlockDescr( context,
originalCode,
consequence,
forDescr,
offset );
}
}
consequence.append( originalCode.substring( lastAdded ) );
// We need to do this as MVEL doesn't recognise "modify"
MacroProcessor macroProcessor = new MacroProcessor();
Map macros = new HashMap( MVELConsequenceBuilder.macros );
macros.put( "modify",
new Macro() {
public String doMacro() {
return "with ";
}
} );
macroProcessor.setMacros( macros );
String mvelCode = macroProcessor.parse( consequence.toString() );
Map<String, Class<?>> inputs = (Map<String, Class<?>> )(Map)getInputs(context, mvelCode, bindings, parentVars);
inputs.putAll( parentVars );
parentBlock.setInputs( inputs );
// now go depth, set inputs for each nested container
// set inputs for current container blocks to be rewritten
for ( JavaBlockDescr block : parentBlock.getJavaBlockDescrs() ) {
if ( block.getType() == BlockType.TRY ) {
JavaTryBlockDescr tryBlock = (JavaTryBlockDescr)block;
setContainerBlockInputs(context,
descrs,
tryBlock,
originalCode.substring( tryBlock.getTextStart()-offset, tryBlock.getEnd()-1-offset ),
bindings,
inputs,
tryBlock.getTextStart() );
for ( JavaCatchBlockDescr catchBlock : tryBlock.getCatches() ) {
setContainerBlockInputs(context,
descrs,
catchBlock,
catchBlock.getClause() + "=null;" + originalCode.substring( catchBlock.getTextStart()-offset, catchBlock.getEnd()-1-offset ),
bindings,
inputs,
tryBlock.getTextStart());
}
if ( tryBlock.getFinal() != null ) {
JavaFinalBlockDescr finalBlock = ( JavaFinalBlockDescr ) tryBlock.getFinal();
setContainerBlockInputs(context,
descrs,
finalBlock,
originalCode.substring( finalBlock.getTextStart()-offset, finalBlock.getEnd()-1-offset ),
bindings,
inputs,
tryBlock.getTextStart());
}
} else if ( block.getType() == BlockType.IF) {
JavaIfBlockDescr ifBlock = (JavaIfBlockDescr)block;
int adjustBlock = (originalCode.charAt( ifBlock.getTextStart()-offset-1 ) == '{') ? 0: 1 ;
setContainerBlockInputs(context,
descrs,
ifBlock,
originalCode.substring( ifBlock.getTextStart()-offset+adjustBlock, ifBlock.getEnd()-1-offset-adjustBlock ),
bindings,
inputs,
ifBlock.getTextStart() );
} else if ( block.getType() == BlockType.ELSE ) {
JavaElseBlockDescr elseBlock = (JavaElseBlockDescr)block;
int adjustBlock = (originalCode.charAt( elseBlock.getTextStart()-offset-1 ) == '{') ? 0: 1 ;
setContainerBlockInputs(context,
descrs,
elseBlock,
originalCode.substring( elseBlock.getTextStart()-offset+adjustBlock, elseBlock.getEnd()-1-offset-adjustBlock ),
bindings,
inputs,
elseBlock.getTextStart() );
} else if ( block.getType() == BlockType.WHILE) {
JavaWhileBlockDescr whileBlock = (JavaWhileBlockDescr)block;
int adjustBlock = (originalCode.charAt( whileBlock.getTextStart()-offset-1 ) == '{') ? 0: 1 ;
setContainerBlockInputs(context,
descrs,
whileBlock,
originalCode.substring( whileBlock.getTextStart()-offset+adjustBlock, whileBlock.getEnd()-1-offset-adjustBlock ),
bindings,
inputs,
whileBlock.getTextStart() );
} else if ( block.getType() == BlockType.FOR) {
JavaForBlockDescr forBlock = (JavaForBlockDescr)block;
int adjustBlock = (originalCode.charAt( forBlock.getTextStart()-offset-1 ) == '{') ? 0: 1 ;
setContainerBlockInputs(context,
descrs,
forBlock,
originalCode.substring( forBlock.getStartParen()-offset,forBlock.getInitEnd()-offset) +
originalCode.substring( forBlock.getTextStart()-offset+adjustBlock, forBlock.getEnd()-1-offset-adjustBlock ),
bindings,
inputs,
forBlock.getTextStart() - (forBlock.getInitEnd()-forBlock.getStartParen() ) );
} else {
block.setInputs(inputs); // each block to be rewritten now knows it's own variables
descrs.add( block );
}
}
}
public Map<String, Class<?>> getInputs(final RuleBuildContext context,
String code,
BoundIdentifiers bindings,
Map<String, Class<?>> parentVars) {
MVELDialect mvel = (MVELDialect) context.getDialect( "mvel" );
MVELAnalysisResult mvelAnalysis = null;
try {
mvelAnalysis = ( MVELAnalysisResult ) mvel.analyzeBlock( context,
context.getRuleDescr(),
null,
code,
bindings,
parentVars,
"drools",
KnowledgeHelper.class );
} catch(Exception e) {
// swallow this as the error will be reported else where
}
return (mvelAnalysis != null) ? mvelAnalysis.getMvelVariables() : new HashMap<String, Class<?>>();
}
private void addWhiteSpaces(String original, StringBuilder consequence, int start, int end) {
for ( int i = start; i < end; i++ ) {
switch(original.charAt( i )) {
case '\n':
case '\r':
case '\t':
case ' ':
consequence.append(original.charAt( i ));
break;
default:
consequence.append( " " );
}
}
}
private void stripTryDescr(RuleBuildContext context,
String originalCode,
StringBuilder consequence,
JavaTryBlockDescr block,
int offset) {
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getTextStart()-offset);
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getEnd()-offset);
for ( JavaCatchBlockDescr catchBlock : block.getCatches() ) {
addWhiteSpaces( originalCode, consequence, consequence.length(),
catchBlock.getTextStart()-offset );
addWhiteSpaces( originalCode, consequence, consequence.length(),
catchBlock.getEnd()-offset );
}
if ( block.getFinal() != null ) {
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getFinal().getTextStart()-offset );
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getFinal().getEnd()-offset );
}
}
private void stripBlockDescr(RuleBuildContext context,
String originalCode,
StringBuilder consequence,
JavaBlockDescr block,
int offset) {
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getEnd()-offset);
}
private void stripElseDescr(RuleBuildContext context,
String originalCode,
StringBuilder consequence,
JavaElseBlockDescr block,
int offset) {
addWhiteSpaces(originalCode, consequence, consequence.length(), block.getEnd()-offset);
}
@SuppressWarnings("unchecked")
private void rewriteInterfacePoint(final RuleBuildContext context,
final String originalCode,
final StringBuilder consequence,
final JavaInterfacePointsDescr ep) {
// rewriting it for proper exitPoints access
consequence.append( "drools.get" );
if ( ep.getType() == BlockType.EXIT ) {
consequence.append( "ExitPoint( " );
} else if( ep.getType() == BlockType.ENTRY ) {
consequence.append( "EntryPoint( " );
} else if( ep.getType() == BlockType.CHANNEL ) {
consequence.append( "Channel( " );
} else {
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
context.getRuleDescr(),
ep,
"Unable to rewrite code block: " + ep + "\n" ) );
return;
}
consequence.append( ep.getId() );
consequence.append( " )" );
// the following is a hack to preserve line breaks.
String originalBlock = originalCode.substring( ep.getStart() - 1,
ep.getEnd() );
int end = originalBlock.indexOf( "]" );
addLineBreaks( consequence,
originalBlock.substring( 0,
end ) );
}
private boolean rewriteDescr(final RuleBuildContext context,
final String originalCode,
MVELDialect mvel,
StringBuilder consequence,
JavaBlockDescr d,
BoundIdentifiers bindings,
Map<String, Declaration> decls) {
if ( d.getEnd() == 0 ) {
// do nothing, it was incorrectly parsed, but this error should be picked up else where
return false;
}
boolean typeSafety = context.isTypesafe();
context.setTypesafe( false ); // we have to analyse in dynamic mode for now, as we cannot safely determine all input vars
MVELAnalysisResult mvelAnalysis = ( MVELAnalysisResult ) mvel.analyzeBlock( context,
context.getRuleDescr(),
mvel.getInterceptors(),
d.getTargetExpression(),
bindings,
d.getInputs(),
"drools",
KnowledgeHelper.class);
context.setTypesafe( typeSafety );
if ( mvelAnalysis == null ) {
// something bad happened, issue already logged in errors
return false;
}
Class ret = mvelAnalysis.getReturnType();
if ( ret == null ) {
// not possible to evaluate expression return value
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
context.getRuleDescr(),
originalCode,
"Unable to determine the resulting type of the expression: " + d.getTargetExpression() + "\n" ) );
return false;
}
// adding modify expression
String retString = ClassUtils.canonicalName( ret );
String declrString;
if (d.getTargetExpression().charAt( 0 ) == '(' ) {
declrString = d.getTargetExpression().substring( 1,d.getTargetExpression().length() -1 ).trim();
} else {
declrString = d.getTargetExpression();
}
String obj = declrString;
Declaration declr = decls.get( declrString );
consequence.append( "{ " );
if ( declr == null ) {
obj = "__obj__";
consequence.append( retString );
consequence.append( " " );
consequence.append( obj);
consequence.append( " = " );
consequence.append( d.getTargetExpression() );
consequence.append( "; " );
}
if ( declr == null || declr.isInternalFact() ) {
consequence.append( "org.drools.FactHandle " );
consequence.append( obj );
consequence.append( "__Handle2__ = drools.getFactHandle(" );
consequence.append( obj );
consequence.append( ");" );
}
// the following is a hack to preserve line breaks.
String originalBlock = originalCode.substring( d.getStart() - 1,
d.getEnd() );
if ( d instanceof JavaModifyBlockDescr ) {
rewriteModifyDescr( context, d, originalBlock, consequence, declr, obj );
} else if ( d instanceof JavaUpdateBlockDescr ) {
rewriteUpdateDescr( d, originalBlock, consequence, declr, obj );
} else if ( d instanceof JavaRetractBlockDescr ) {
rewriteRetractDescr( d, originalBlock, consequence, declr, obj );
}
return declr != null;
}
private boolean rewriteModifyDescr(final RuleBuildContext context,
JavaBlockDescr d,
String originalBlock,
StringBuilder consequence,
Declaration declr,
String obj) {
int end = originalBlock.indexOf( "{" );
if( end == -1 ){
// no block
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
context.getRuleDescr(),
null,
"Block missing after modify" + d.getTargetExpression() + " ?\n" ) );
return false;
}
addLineBreaks( consequence,
originalBlock.substring( 0,
end ) );
int start = end + 1;
// adding each of the expressions:
for ( String exprStr : ((JavaModifyBlockDescr)d).getExpressions() ) {
end = originalBlock.indexOf( exprStr,
start );
addLineBreaks( consequence,
originalBlock.substring( start,
end ) );
consequence.append( obj + "." );
consequence.append( exprStr );
consequence.append( "; " );
start = end + exprStr.length();
}
// adding the modifyInsert call:
addLineBreaks( consequence,
originalBlock.substring( end ) );
if ( declr != null && !declr.isInternalFact() ) {
consequence.append( "drools.update( " + obj + "__Handle__ ); }" );
} else {
consequence.append( "drools.update( " + obj + "__Handle2__ ); }" );
}
return declr != null;
}
private boolean rewriteUpdateDescr(JavaBlockDescr d,
String originalBlock,
StringBuilder consequence,
Declaration declr,
String obj) {
if ( declr != null && !declr.isInternalFact() ) {
consequence.append( "drools.update( " + obj + "__Handle__ ); }" );
} else {
consequence.append( "drools.update( " + obj + "__Handle2__ ); }" );
}
return declr != null;
}
private boolean rewriteRetractDescr(JavaBlockDescr d,
String originalBlock,
StringBuilder consequence,
Declaration declr,
String obj) {
if ( declr != null && !declr.isInternalFact() ) {
consequence.append( "drools.retract( " + obj + "__Handle__ ); }" );
} else {
consequence.append( "drools.retract( " + obj + "__Handle2__ ); }" );
}
return declr != null;
}
/**
* @param consequence
* @param chunk
*/
private void addLineBreaks(StringBuilder consequence,
String chunk) {
Matcher m = lineBreakFinder.matcher( chunk );
while ( m.find() ) {
consequence.append( "\n" );
}
}
}