package org.jboss.seam.drools;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import org.drools.RuleBaseConfiguration;
import org.drools.RuleBaseFactory;
import org.drools.compiler.DroolsError;
import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.compiler.RuleBuildError;
import org.drools.spi.ConsequenceExceptionHandler;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Unwrap;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.core.ResourceLoader;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* Manager component for a Drools RuleBase
*
* @author Gavin King
* @author Tihomir Surdilovic
*
*/
@Scope(ScopeType.APPLICATION)
@BypassInterceptors
public class RuleBase
{
private static final LogProvider log = Logging.getLogProvider(RuleBase.class);
private String[] ruleFiles;
private String dslFile;
private ValueExpression<ConsequenceExceptionHandler> consequenceExceptionHandler;
private org.drools.RuleBase ruleBase;
@Create
public void compileRuleBase() throws Exception
{
PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
PackageBuilder builder = new PackageBuilder(conf);
if (ruleFiles!=null)
{
for (String ruleFile: ruleFiles)
{
log.debug("parsing rules: " + ruleFile);
InputStream stream = ResourceLoader.instance().getResourceAsStream(ruleFile);
if (stream==null)
{
throw new IllegalStateException("could not locate rule file: " + ruleFile);
}
if(isDecisionTable(ruleFile))
{
if (SpreadsheetCompiler.instance() != null) {
builder.addPackageFromDrl(SpreadsheetCompiler.instance().compile(stream));
} else {
throw new UnsupportedOperationException("Unable to compile decision table. You need drools-decisiontables.jar in your classpath");
}
}
else if(isRuleFlow(ruleFile))
{
log.debug("adding ruleflow: " + ruleFile);
builder.addRuleFlow( new InputStreamReader(stream) );
}
else
{
// read in the source
Reader drlReader = new InputStreamReader(stream);
if (dslFile==null)
{
builder.addPackageFromDrl(drlReader);
}
else
{
Reader dslReader = new InputStreamReader( ResourceLoader.instance().getResourceAsStream(dslFile) );
builder.addPackageFromDrl(drlReader, dslReader);
}
}
if ( builder.hasErrors() )
{
log.error("errors parsing rules in: " + ruleFile);
for ( DroolsError error: builder.getErrors().getErrors() )
{
if (error instanceof RuleBuildError)
{
RuleBuildError ruleError = (RuleBuildError) error;
log.error( ruleError.getMessage() + " (" + ruleFile + ':' + ruleError.getLine() + ')' );
}
else
{
log.error( error.getMessage() + " (" + ruleFile + ')' );
}
}
}
}
}
if(consequenceExceptionHandler != null)
{
log.debug("adding consequence exception handler: " + consequenceExceptionHandler.getExpressionString());
RuleBaseConfiguration rbconf = new RuleBaseConfiguration();
rbconf.setConsequenceExceptionHandler(consequenceExceptionHandler.getValue().toString());
ruleBase = RuleBaseFactory.newRuleBase( rbconf );
}
else
{
ruleBase = RuleBaseFactory.newRuleBase();
}
ruleBase.addPackage( builder.getPackage() );
}
@Unwrap
public org.drools.RuleBase getRuleBase()
{
return ruleBase;
}
public String[] getRuleFiles()
{
return ruleFiles;
}
public void setRuleFiles(String[] ruleFiles)
{
this.ruleFiles = ruleFiles;
}
public String getDslFile()
{
return dslFile;
}
public void setDslFile(String dslFile)
{
this.dslFile = dslFile;
}
public ValueExpression<ConsequenceExceptionHandler> getConsequenceExceptionHandler()
{
return consequenceExceptionHandler;
}
public void setConsequenceExceptionHandler(ValueExpression<ConsequenceExceptionHandler> consequenceExceptionHandler)
{
this.consequenceExceptionHandler = consequenceExceptionHandler;
}
private boolean isDecisionTable(String fileName)
{
return fileName != null && fileName.length() > 0 && fileName.endsWith(".xls");
}
private boolean isRuleFlow(String fileName)
{
//support both new drools5 and older drools4 formats
return fileName != null && fileName.length() > 0 && (fileName.endsWith(".rf") || fileName.endsWith(".rfm"));
}
}