[jboss-svn-commits] JBL Code SVN: r9959 - in labs/jbossrules/trunk/drools-compiler/src: main/java/org/drools/lang/descr and 3 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sun Mar 4 22:56:07 EST 2007
Author: mark.proctor at jboss.com
Date: 2007-03-04 22:56:07 -0500 (Sun, 04 Mar 2007)
New Revision: 9959
Added:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/DialectRegistry.java
Removed:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/CompilerHelper.java
Modified:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldConstraintDescr.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/Dialect.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java
Log:
JBRULES-713 Make Dialects Pluggeable
Deleted: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/CompilerHelper.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/CompilerHelper.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/CompilerHelper.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -1,312 +0,0 @@
-package org.drools.compiler;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.jci.compilers.CompilationResult;
-import org.apache.commons.jci.compilers.EclipseJavaCompiler;
-import org.apache.commons.jci.compilers.EclipseJavaCompilerSettings;
-import org.apache.commons.jci.compilers.JavaCompiler;
-import org.apache.commons.jci.compilers.JavaCompilerFactory;
-import org.apache.commons.jci.problems.CompilationProblem;
-import org.apache.commons.jci.readers.MemoryResourceReader;
-import org.apache.commons.jci.readers.ResourceReader;
-import org.codehaus.jfdi.interpreter.TypeResolver;
-import org.drools.RuntimeDroolsException;
-import org.drools.compiler.PackageBuilder.ErrorHandler;
-import org.drools.compiler.PackageBuilder.FunctionErrorHandler;
-import org.drools.compiler.PackageBuilder.RuleErrorHandler;
-import org.drools.compiler.PackageBuilder.RuleInvokerErrorHandler;
-import org.drools.lang.descr.BaseDescr;
-import org.drools.lang.descr.FunctionDescr;
-import org.drools.lang.descr.RuleDescr;
-import org.drools.rule.LineMappings;
-import org.drools.rule.Package;
-import org.drools.rule.Rule;
-import org.drools.rule.builder.FunctionBuilder;
-import org.drools.rule.builder.RuleBuilder;
-import org.drools.rule.builder.dialect.java.JavaFunctionBuilder;
-import org.drools.rule.builder.dialect.java.PackageStore;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-
-public class CompilerHelper {
- private Package pkg;
- private JavaCompiler compiler;
- private List generatedClassList;
- private PackageBuilderConfiguration configuration;
-
- private MemoryResourceReader src;
- private PackageStore packageStoreWrapper;
-
- private Map lineMappings;
-
- private Map errorHandlers;
-
- private List results;
-
- public CompilerHelper(final Package pkg,
- PackageBuilderConfiguration configuration) {
- this.pkg = pkg;
- this.configuration = configuration;
- loadCompiler();
-
- if ( pkg != null ) {
- init( pkg );
- }
- }
-
- public void init(Package pkg) {
- this.pkg = pkg;
- this.errorHandlers = new HashMap();
-
- this.src = new MemoryResourceReader();
- if ( pkg != null ) {
- this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
- this.lineMappings = pkg.getPackageCompilationData().getLineMappings();
- }
-
- this.generatedClassList = new ArrayList();
-
- this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
- this.lineMappings = new HashMap();
- pkg.getPackageCompilationData().setLineMappings( this.lineMappings );
-
- this.results = new ArrayList();
- }
-
- public void init(RuleDescr ruleDescr) {
- final String ruleClassName = getUniqueLegalName( this.pkg.getName(),
- ruleDescr.getName(),
- "java",
- this.src );
- ruleDescr.setClassName( ucFirst( ruleClassName ) );
- }
-
- /**
- * This actually triggers the compiling of all the resources.
- * Errors are mapped back to the element that originally generated the semantic
- * code.
- */
- public void compileAll() {
- if ( this.generatedClassList.isEmpty() ) {
- return;
- }
- final String[] classes = new String[this.generatedClassList.size()];
- this.generatedClassList.toArray( classes );
-
- final CompilationResult result = this.compiler.compile( classes,
- this.src,
- this.packageStoreWrapper,
- this.pkg.getPackageCompilationData().getClassLoader() );
-
- //this will sort out the errors based on what class/file they happened in
- if ( result.getErrors().length > 0 ) {
- for ( int i = 0; i < result.getErrors().length; i++ ) {
- final CompilationProblem err = result.getErrors()[i];
-
- final ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
- if ( handler instanceof RuleErrorHandler ) {
- final RuleErrorHandler rh = (RuleErrorHandler) handler;
- }
- handler.addError( err );
- }
-
- final Collection errors = this.errorHandlers.values();
- for ( final Iterator iter = errors.iterator(); iter.hasNext(); ) {
- final ErrorHandler handler = (ErrorHandler) iter.next();
- if ( handler.isInError() ) {
- if ( !(handler instanceof RuleInvokerErrorHandler) ) {
- this.results.add( handler.getError() );
- } else {
- //we don't really want to report invoker errors.
- //mostly as they can happen when there is a syntax error in the RHS
- //and otherwise, it is a programmatic error in drools itself.
- System.err.println( "Warning: An error occurred compiling a semantic invoker. Errors should have been reported elsewhere." );
- }
- }
- }
- }
- }
-
- /**
- * This will setup the semantic components of the rule for compiling later on.
- * It will not actually call the compiler
- */
- public void addRuleSemantics(final RuleBuilder builder,
- final Rule rule,
- final RuleDescr ruleDescr) {
- // return if there is no ruleclass name;
- if ( builder.getRuleClass() == null ) {
- return;
- }
-
- // The compilation result is for th entire rule, so difficult to associate with any descr
- addClassCompileTask( this.pkg.getName() + "." + ruleDescr.getClassName(),
- ruleDescr,
- builder.getRuleClass(),
- this.src,
- new RuleErrorHandler( ruleDescr,
- rule,
- "Rule Compilation error" ) );
-
- for ( final Iterator it = builder.getInvokers().keySet().iterator(); it.hasNext(); ) {
- final String className = (String) it.next();
-
- // Check if an invoker - returnvalue, predicate, eval or consequence has been associated
- // If so we add it to the PackageCompilationData as it will get wired up on compilation
- final Object invoker = builder.getInvokerLookups().get( className );
- if ( invoker != null ) {
- this.pkg.getPackageCompilationData().putInvoker( className,
- invoker );
- }
- final String text = (String) builder.getInvokers().get( className );
-
- //System.out.println( className + ":\n" + text );
- final BaseDescr descr = (BaseDescr) builder.getDescrLookups().get( className );
- addClassCompileTask( className,
- descr,
- text,
- this.src,
- new RuleInvokerErrorHandler( descr,
- rule,
- "Unable to generate rule invoker." ) );
-
- }
-
- // setup the line mappins for this rule
- String name = pkg.getName() + "." + ucFirst( ruleDescr.getClassName() );
- LineMappings mapping = new LineMappings( name );
- mapping.setStartLine( ruleDescr.getConsequenceLine() );
- mapping.setOffset( ruleDescr.getConsequenceOffset() );
- this.lineMappings.put( name,
- mapping );
- }
-
- public void addFunction(final FunctionDescr functionDescr,
- TypeResolver typeResolver) {
-
- String functionClassName = this.pkg.getName() + "." + ucFirst( functionDescr.getName() );
- this.pkg.addStaticImport( functionClassName + "." + functionDescr.getName() );
- functionDescr.setClassName( functionClassName );
-
- final FunctionBuilder builder = new JavaFunctionBuilder();
- this.pkg.addFunction( functionDescr.getName() );
-
- addClassCompileTask( functionClassName,
- functionDescr,
- builder.build( this.pkg,
- functionDescr,
- typeResolver,
- lineMappings ),
- this.src,
- new FunctionErrorHandler( functionDescr,
- "Function Compilation error" ) );
-
- LineMappings mapping = new LineMappings( functionClassName );
- mapping.setStartLine( functionDescr.getLine() );
- mapping.setOffset( functionDescr.getOffset() );
- this.lineMappings.put( functionClassName,
- mapping );
- }
-
- /**
- * This adds a compile "task" for when the compiler of
- * semantics (JCI) is called later on with compileAll()\
- * which actually does the compiling.
- * The ErrorHandler is required to map the errors back to the
- * element that caused it.
- */
- private void addClassCompileTask(final String className,
- final BaseDescr descr,
- final String text,
- final MemoryResourceReader src,
- final ErrorHandler handler) {
-
- final String fileName = className.replace( '.',
- '/' ) + ".java";
-
- src.add( fileName,
- text.getBytes() );
-
- this.errorHandlers.put( fileName,
- handler );
-
- addClassName( fileName );
- }
-
- public void addClassName(String className) {
- this.generatedClassList.add( className );
- }
-
- private void loadCompiler() {
- switch ( this.configuration.getCompiler() ) {
- case PackageBuilderConfiguration.JANINO : {
- if ( !"1.4".equals( this.configuration.getJavaLanguageLevel() ) ) {
- throw new RuntimeDroolsException( "Incompatible Java language level with selected compiler" );
- }
- this.compiler = JavaCompilerFactory.getInstance().createCompiler( "janino" );
- break;
- }
- case PackageBuilderConfiguration.ECLIPSE :
- default : {
- final EclipseJavaCompilerSettings eclipseSettings = new EclipseJavaCompilerSettings();
- Map map = eclipseSettings.getMap();
- map.put( CompilerOptions.OPTION_TargetPlatform,
- this.configuration.getJavaLanguageLevel() );
-
- // We now default this to 1.5, so we can use static imports.
- map.put( CompilerOptions.OPTION_Source,
- "1.5" );
- this.compiler = new EclipseJavaCompiler( map );
- break;
- }
- }
- }
-
- public List getResults() {
- return this.results;
- }
-
- /**
- * Takes a given name and makes sure that its legal and doesn't already exist. If the file exists it increases counter appender untill it is unique.
- *
- * @param packageName
- * @param name
- * @param ext
- * @return
- */
- private String getUniqueLegalName(final String packageName,
- final String name,
- final String ext,
- final ResourceReader src) {
- // replaces all non alphanumeric or $ chars with _
- String newName = "Rule_" + name.replaceAll( "[^\\w$]",
- "_" );
-
- // make sure the class name does not exist, if it does increase the counter
- int counter = -1;
- boolean exists = true;
- while ( exists ) {
-
- counter++;
- final String fileName = packageName.replaceAll( "\\.",
- "/" ) + newName + "_" + counter + ext;
-
- exists = src.isAvailable( fileName );
- }
- // we have duplicate file names so append counter
- if ( counter >= 0 ) {
- newName = newName + "_" + counter;
- }
-
- return newName;
- }
-
- private String ucFirst(final String name) {
- return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
- }
-}
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/DialectRegistry.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/DialectRegistry.java (rev 0)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/DialectRegistry.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -0,0 +1,23 @@
+package org.drools.compiler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.rule.builder.Dialect;
+
+public class DialectRegistry {
+ private Map map;
+
+ public DialectRegistry() {
+ this.map = new HashMap();
+ }
+
+ public void addDialect(String name, Dialect dialect) {
+ this.map.put( name, dialect );
+ }
+
+ public Dialect getDialect(String name) {
+ return ( Dialect ) this.map.get( name );
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -55,6 +55,7 @@
import org.drools.rule.LineMappings;
import org.drools.rule.Package;
import org.drools.rule.Rule;
+import org.drools.rule.builder.Dialect;
import org.drools.rule.builder.FunctionBuilder;
import org.drools.rule.builder.RuleBuilder;
import org.drools.rule.builder.dialect.java.JavaDialect;
@@ -71,21 +72,23 @@
* This can be done by merging into existing binary packages, or totally from source.
*/
public class PackageBuilder {
-
+
private Package pkg;
-
+
private List results;
-
+
private PackageBuilderConfiguration configuration;
private TypeResolver typeResolver;
-
+
private ClassFieldExtractorCache classFieldExtractorCache;
private RuleBuilder builder;
-
- private CompilerHelper helper;
+ private Dialect dialect;
+
+ private DialectRegistry dialects;
+
/**
* Use this when package is starting from scratch.
*/
@@ -116,14 +119,19 @@
PackageBuilderConfiguration configuration) {
if ( configuration == null ) {
configuration = new PackageBuilderConfiguration();
- }
+ }
- this.helper = new CompilerHelper(pkg, configuration);
-
this.configuration = configuration;
this.results = new ArrayList();
- this.pkg = pkg;
+ this.pkg = pkg;
this.classFieldExtractorCache = new ClassFieldExtractorCache();
+
+ this.dialects = new DialectRegistry();
+ this.dialects.addDialect( "java",
+ new JavaDialect( pkg,
+ configuration ) );
+
+ this.dialect = this.dialects.getDialect( "java" );
}
/**
@@ -197,7 +205,7 @@
builder = new RuleBuilder( getTypeResolver(),
this.classFieldExtractorCache,
- new JavaDialect() );
+ this.dialect );
//only try to compile if there are no parse errors
if ( !hasErrors() ) {
@@ -215,10 +223,10 @@
addRule( (RuleDescr) it.next() );
}
}
-
- this.helper.compileAll();
-
- this.results.addAll( this.helper.getResults() );
+
+ this.dialect.compileAll();
+
+ this.results.addAll( this.dialect.getResults() );
}
private void validatePackageName(final PackageDescr packageDescr) {
@@ -245,9 +253,9 @@
private Package newPackage(final PackageDescr packageDescr) {
final Package pkg = new Package( packageDescr.getName(),
this.configuration.getClassLoader() );
-
- this.helper.init( pkg );
+ this.dialect.init( pkg );
+
mergePackage( pkg,
packageDescr );
@@ -285,10 +293,9 @@
}
}
-
-
private void addFunction(final FunctionDescr functionDescr) {
- this.helper.addFunction(functionDescr, getTypeResolver() );
+ this.dialect.addFunction( functionDescr,
+ getTypeResolver() );
}
private void addFactTemplate(final FactTemplateDescr factTemplateDescr) {
@@ -316,21 +323,19 @@
}
private void addRule(final RuleDescr ruleDescr) {
- this.helper.init( ruleDescr );
-
+ this.dialect.init( ruleDescr );
+
builder.build( this.pkg,
ruleDescr );
-
this.results.addAll( builder.getErrors() );
final Rule rule = builder.getRule();
+ this.dialect.addRuleSemantics( builder,
+ rule,
+ ruleDescr );
- this.helper.addRuleSemantics( builder,
- rule,
- ruleDescr );
-
this.pkg.addRule( rule );
}
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldConstraintDescr.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldConstraintDescr.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldConstraintDescr.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
/*
@@ -49,6 +50,16 @@
public List getRestrictions() {
return this.restrictions;
}
+
+/* public boolean isBound(String identifier) {
+ for ( Iterator it = this.restrictions.iterator(); it.hasNext(); ) {
+ Object object = it.next();
+ if ( object instanceof FieldBindingDescr ) {
+ FieldBindingDescr descr =
+ }
+ }
+ return false;
+ }*/
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/Dialect.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/Dialect.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/Dialect.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -1,6 +1,13 @@
package org.drools.rule.builder;
+import java.util.List;
+
+import org.codehaus.jfdi.interpreter.TypeResolver;
+import org.drools.lang.descr.FunctionDescr;
+import org.drools.lang.descr.RuleDescr;
import org.drools.reteoo.builder.EvalBuilder;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
public interface Dialect {
ConditionalElementBuilder getEvalBuilder();
@@ -17,4 +24,18 @@
FromBuilder getFromBuilder();
+ void compileAll();
+
+ void addRuleSemantics(final RuleBuilder builder,
+ final Rule rule,
+ final RuleDescr ruleDescr);
+
+ void addFunction(final FunctionDescr functionDescr,
+ TypeResolver typeResolver);
+
+ List getResults();
+
+ void init(Package pkg);
+
+ void init(RuleDescr ruleDescr);
}
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/java/JavaDialect.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -1,16 +1,59 @@
package org.drools.rule.builder.dialect.java;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.jci.compilers.CompilationResult;
+import org.apache.commons.jci.compilers.EclipseJavaCompiler;
+import org.apache.commons.jci.compilers.EclipseJavaCompilerSettings;
+import org.apache.commons.jci.compilers.JavaCompiler;
+import org.apache.commons.jci.compilers.JavaCompilerFactory;
+import org.apache.commons.jci.problems.CompilationProblem;
+import org.apache.commons.jci.readers.MemoryResourceReader;
+import org.apache.commons.jci.readers.ResourceReader;
+import org.codehaus.jfdi.interpreter.TypeResolver;
+import org.drools.RuntimeDroolsException;
+import org.drools.compiler.PackageBuilderConfiguration;
+import org.drools.compiler.PackageBuilder.ErrorHandler;
+import org.drools.compiler.PackageBuilder.FunctionErrorHandler;
+import org.drools.compiler.PackageBuilder.RuleErrorHandler;
+import org.drools.compiler.PackageBuilder.RuleInvokerErrorHandler;
+import org.drools.lang.descr.AccumulateDescr;
+import org.drools.lang.descr.AndDescr;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.lang.descr.CollectDescr;
+import org.drools.lang.descr.EvalDescr;
+import org.drools.lang.descr.ExistsDescr;
+import org.drools.lang.descr.ForallDescr;
+import org.drools.lang.descr.FromDescr;
+import org.drools.lang.descr.FunctionDescr;
+import org.drools.lang.descr.NotDescr;
+import org.drools.lang.descr.OrDescr;
+import org.drools.lang.descr.RuleDescr;
import org.drools.reteoo.builder.EvalBuilder;
+import org.drools.rule.LineMappings;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
import org.drools.rule.builder.AccumulateBuilder;
+import org.drools.rule.builder.CollectBuilder;
+import org.drools.rule.builder.ColumnBuilder;
import org.drools.rule.builder.ConditionalElementBuilder;
import org.drools.rule.builder.ConsequenceBuilder;
import org.drools.rule.builder.Dialect;
+import org.drools.rule.builder.ForallBuilder;
import org.drools.rule.builder.FromBuilder;
+import org.drools.rule.builder.FunctionBuilder;
+import org.drools.rule.builder.GroupElementBuilder;
import org.drools.rule.builder.PredicateBuilder;
import org.drools.rule.builder.ReturnValueBuilder;
import org.drools.rule.builder.RuleBuilder;
import org.drools.rule.builder.RuleClassBuilder;
import org.drools.rule.builder.dialect.mvel.MVELFromBuilder;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
public class JavaDialect
implements
@@ -24,7 +67,112 @@
private JavaRuleClassBuilder rule = new JavaRuleClassBuilder();
private MVELFromBuilder from = new MVELFromBuilder();
+ private Package pkg;
+ private JavaCompiler compiler;
+ private List generatedClassList;
+ private PackageBuilderConfiguration configuration;
+
+ private MemoryResourceReader src;
+ private PackageStore packageStoreWrapper;
+
+ private Map lineMappings;
+
+ private Map errorHandlers;
+
+ private List results;
+ // a map of registered builders
+ private Map builders;
+
+ // the builder for columns
+ private ColumnBuilder columnBuilder;
+
+ // the builder for the consequence
+ private ConsequenceBuilder consequenceBuilder;
+
+ // the builder for the rule class
+ private RuleClassBuilder classBuilder;
+
+ public JavaDialect(final Package pkg,
+ PackageBuilderConfiguration configuration) {
+ this.pkg = pkg;
+ this.configuration = configuration;
+ loadCompiler();
+
+ if ( pkg != null ) {
+ init( pkg );
+ }
+
+ initBuilder();
+ }
+
+ public void initBuilder() {
+ // statically adding all builders to the map
+ // but in the future we can move that to a configuration
+ // if we want to
+ this.builders = new HashMap();
+
+ builders.put( CollectDescr.class,
+ new CollectBuilder() );
+
+ builders.put( ForallDescr.class,
+ new ForallBuilder() );
+ GroupElementBuilder gebuilder = new GroupElementBuilder();
+ builders.put( AndDescr.class,
+ gebuilder );
+ builders.put( OrDescr.class,
+ gebuilder );
+ builders.put( NotDescr.class,
+ gebuilder );
+ builders.put( ExistsDescr.class,
+ gebuilder );
+
+ // dialect specific
+ this.columnBuilder = new ColumnBuilder( this );
+
+ builders.put( FromDescr.class,
+ getFromBuilder() );
+
+ builders.put( AccumulateDescr.class,
+ getAccumulateBuilder() );
+
+ builders.put( EvalDescr.class,
+ getEvalBuilder() );
+
+ this.consequenceBuilder = (ConsequenceBuilder) getConsequenceBuilder();
+
+ this.classBuilder = (RuleClassBuilder) getRuleClassBuilder();
+ }
+
+ public void init(Package pkg) {
+ this.pkg = pkg;
+ this.errorHandlers = new HashMap();
+
+ this.src = new MemoryResourceReader();
+ if ( pkg != null ) {
+ this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
+ this.lineMappings = pkg.getPackageCompilationData().getLineMappings();
+ }
+
+ this.generatedClassList = new ArrayList();
+
+ this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
+ this.lineMappings = new HashMap();
+ pkg.getPackageCompilationData().setLineMappings( this.lineMappings );
+
+ this.results = new ArrayList();
+ }
+
+ public void init(RuleDescr ruleDescr) {
+ final String ruleClassName = getUniqueLegalName( this.pkg.getName(),
+ ruleDescr.getName(),
+ "java",
+ this.src );
+ ruleDescr.setClassName( ucFirst( ruleClassName ) );
+ }
+
+
+
public AccumulateBuilder getAccumulateBuilder() {
return this.accumulate;
}
@@ -51,6 +199,231 @@
public FromBuilder getFromBuilder() {
return this.from;
+ }
+
+ /**
+ * This actually triggers the compiling of all the resources.
+ * Errors are mapped back to the element that originally generated the semantic
+ * code.
+ */
+ public void compileAll() {
+ if ( this.generatedClassList.isEmpty() ) {
+ return;
+ }
+ final String[] classes = new String[this.generatedClassList.size()];
+ this.generatedClassList.toArray( classes );
+
+ final CompilationResult result = this.compiler.compile( classes,
+ this.src,
+ this.packageStoreWrapper,
+ this.pkg.getPackageCompilationData().getClassLoader() );
+
+ //this will sort out the errors based on what class/file they happened in
+ if ( result.getErrors().length > 0 ) {
+ for ( int i = 0; i < result.getErrors().length; i++ ) {
+ final CompilationProblem err = result.getErrors()[i];
+
+ final ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
+ if ( handler instanceof RuleErrorHandler ) {
+ final RuleErrorHandler rh = (RuleErrorHandler) handler;
+ }
+ handler.addError( err );
+ }
+
+ final Collection errors = this.errorHandlers.values();
+ for ( final Iterator iter = errors.iterator(); iter.hasNext(); ) {
+ final ErrorHandler handler = (ErrorHandler) iter.next();
+ if ( handler.isInError() ) {
+ if ( !(handler instanceof RuleInvokerErrorHandler) ) {
+ this.results.add( handler.getError() );
+ } else {
+ //we don't really want to report invoker errors.
+ //mostly as they can happen when there is a syntax error in the RHS
+ //and otherwise, it is a programmatic error in drools itself.
+ System.err.println( "Warning: An error occurred compiling a semantic invoker. Errors should have been reported elsewhere." );
+ }
+ }
+ }
+ }
}
+ /**
+ * This will setup the semantic components of the rule for compiling later on.
+ * It will not actually call the compiler
+ */
+ public void addRuleSemantics(final RuleBuilder builder,
+ final Rule rule,
+ final RuleDescr ruleDescr) {
+ // return if there is no ruleclass name;
+ if ( builder.getRuleClass() == null ) {
+ return;
+ }
+
+ // The compilation result is for th entire rule, so difficult to associate with any descr
+ addClassCompileTask( this.pkg.getName() + "." + ruleDescr.getClassName(),
+ ruleDescr,
+ builder.getRuleClass(),
+ this.src,
+ new RuleErrorHandler( ruleDescr,
+ rule,
+ "Rule Compilation error" ) );
+
+ for ( final Iterator it = builder.getInvokers().keySet().iterator(); it.hasNext(); ) {
+ final String className = (String) it.next();
+
+ // Check if an invoker - returnvalue, predicate, eval or consequence has been associated
+ // If so we add it to the PackageCompilationData as it will get wired up on compilation
+ final Object invoker = builder.getInvokerLookups().get( className );
+ if ( invoker != null ) {
+ this.pkg.getPackageCompilationData().putInvoker( className,
+ invoker );
+ }
+ final String text = (String) builder.getInvokers().get( className );
+
+ //System.out.println( className + ":\n" + text );
+ final BaseDescr descr = (BaseDescr) builder.getDescrLookups().get( className );
+ addClassCompileTask( className,
+ descr,
+ text,
+ this.src,
+ new RuleInvokerErrorHandler( descr,
+ rule,
+ "Unable to generate rule invoker." ) );
+
+ }
+
+ // setup the line mappins for this rule
+ String name = pkg.getName() + "." + ucFirst( ruleDescr.getClassName() );
+ LineMappings mapping = new LineMappings( name );
+ mapping.setStartLine( ruleDescr.getConsequenceLine() );
+ mapping.setOffset( ruleDescr.getConsequenceOffset() );
+ this.lineMappings.put( name,
+ mapping );
+ }
+
+ public void addFunction(final FunctionDescr functionDescr,
+ TypeResolver typeResolver) {
+
+ String functionClassName = this.pkg.getName() + "." + ucFirst( functionDescr.getName() );
+ this.pkg.addStaticImport( functionClassName + "." + functionDescr.getName() );
+ functionDescr.setClassName( functionClassName );
+
+ final FunctionBuilder builder = new JavaFunctionBuilder();
+ this.pkg.addFunction( functionDescr.getName() );
+
+ addClassCompileTask( functionClassName,
+ functionDescr,
+ builder.build( this.pkg,
+ functionDescr,
+ typeResolver,
+ lineMappings ),
+ this.src,
+ new FunctionErrorHandler( functionDescr,
+ "Function Compilation error" ) );
+
+ LineMappings mapping = new LineMappings( functionClassName );
+ mapping.setStartLine( functionDescr.getLine() );
+ mapping.setOffset( functionDescr.getOffset() );
+ this.lineMappings.put( functionClassName,
+ mapping );
+ }
+
+ /**
+ * This adds a compile "task" for when the compiler of
+ * semantics (JCI) is called later on with compileAll()\
+ * which actually does the compiling.
+ * The ErrorHandler is required to map the errors back to the
+ * element that caused it.
+ */
+ private void addClassCompileTask(final String className,
+ final BaseDescr descr,
+ final String text,
+ final MemoryResourceReader src,
+ final ErrorHandler handler) {
+
+ final String fileName = className.replace( '.',
+ '/' ) + ".java";
+
+ src.add( fileName,
+ text.getBytes() );
+
+ this.errorHandlers.put( fileName,
+ handler );
+
+ addClassName( fileName );
+ }
+
+ public void addClassName(String className) {
+ this.generatedClassList.add( className );
+ }
+
+ private void loadCompiler() {
+ switch ( this.configuration.getCompiler() ) {
+ case PackageBuilderConfiguration.JANINO : {
+ if ( !"1.4".equals( this.configuration.getJavaLanguageLevel() ) ) {
+ throw new RuntimeDroolsException( "Incompatible Java language level with selected compiler" );
+ }
+ this.compiler = JavaCompilerFactory.getInstance().createCompiler( "janino" );
+ break;
+ }
+ case PackageBuilderConfiguration.ECLIPSE :
+ default : {
+ final EclipseJavaCompilerSettings eclipseSettings = new EclipseJavaCompilerSettings();
+ Map map = eclipseSettings.getMap();
+ map.put( CompilerOptions.OPTION_TargetPlatform,
+ this.configuration.getJavaLanguageLevel() );
+
+ // We now default this to 1.5, so we can use static imports.
+ map.put( CompilerOptions.OPTION_Source,
+ "1.5" );
+ this.compiler = new EclipseJavaCompiler( map );
+ break;
+ }
+ }
+ }
+
+ public List getResults() {
+ return this.results;
+ }
+
+ /**
+ * Takes a given name and makes sure that its legal and doesn't already exist. If the file exists it increases counter appender untill it is unique.
+ *
+ * @param packageName
+ * @param name
+ * @param ext
+ * @return
+ */
+ private String getUniqueLegalName(final String packageName,
+ final String name,
+ final String ext,
+ final ResourceReader src) {
+ // replaces all non alphanumeric or $ chars with _
+ String newName = "Rule_" + name.replaceAll( "[^\\w$]",
+ "_" );
+
+ // make sure the class name does not exist, if it does increase the counter
+ int counter = -1;
+ boolean exists = true;
+ while ( exists ) {
+
+ counter++;
+ final String fileName = packageName.replaceAll( "\\.",
+ "/" ) + newName + "_" + counter + ext;
+
+ exists = src.isAvailable( fileName );
+ }
+ // we have duplicate file names so append counter
+ if ( counter >= 0 ) {
+ newName = newName + "_" + counter;
+ }
+
+ return newName;
+ }
+
+ private String ucFirst(final String name) {
+ return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
+ }
+
+
}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java 2007-03-05 02:53:08 UTC (rev 9958)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java 2007-03-05 03:56:07 UTC (rev 9959)
@@ -29,6 +29,7 @@
import org.codehaus.jfdi.interpreter.TypeResolver;
import org.drools.base.ClassFieldExtractorCache;
import org.drools.compiler.DrlParser;
+import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.lang.descr.AttributeDescr;
import org.drools.lang.descr.PackageDescr;
import org.drools.lang.descr.RuleDescr;
@@ -84,7 +85,7 @@
final RuleBuilder builder = new RuleBuilder( typeResolver,
new ClassFieldExtractorCache(),
- new JavaDialect() );
+ new JavaDialect(null, new PackageBuilderConfiguration() ) );
builder.build( pkg,
ruleDescr );
@@ -120,7 +121,7 @@
}
public void testBuildAttributes() throws Exception {
- RuleBuilder builder = new RuleBuilder(null, null, new JavaDialect() );
+ RuleBuilder builder = new RuleBuilder(null, null, new JavaDialect(null, new PackageBuilderConfiguration()) );
Rule rule = new Rule("myrule");
List attributes = new ArrayList();
More information about the jboss-svn-commits
mailing list