[jboss-svn-commits] JBL Code SVN: r6045 - in labs/jbossrules/trunk/drools-compiler/src: main/java/org/drools/compiler main/java/org/drools/semantics/java test/java/org/drools test/java/org/drools/integrationtests test/java/org/drools/semantics/java test/resources/org/drools/integrationtests

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Aug 31 12:53:39 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-08-31 12:53:31 -0400 (Thu, 31 Aug 2006)
New Revision: 6045

Added:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/StaticMethodFunctionResolver.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Func.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods2.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/StaticMethodFunctionResolverTest.java
   labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ImportFunctions.drl
Modified:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/FunctionFixer.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/IntegrationCases.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/FunctionFixerTest.java
Log:
JBRULES-468 import functions from static methods

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	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -51,8 +51,11 @@
 import org.drools.rule.Rule;
 import org.drools.semantics.java.ClassTypeResolver;
 import org.drools.semantics.java.FunctionBuilder;
+import org.drools.semantics.java.FunctionFixer;
 import org.drools.semantics.java.PackageStore;
 import org.drools.semantics.java.RuleBuilder;
+import org.drools.semantics.java.StaticMethodFunctionResolver;
+import org.drools.spi.FunctionResolver;
 import org.drools.spi.TypeResolver;
 import org.drools.xml.XmlPackageReader;
 import org.xml.sax.SAXException;
@@ -72,7 +75,9 @@
     private PackageBuilderConfiguration configuration;
     private Map                         errorHandlers;
     private List                        generatedClassList;
-    private ClassTypeResolver           typeResolver;
+    private TypeResolver                typeResolver;
+    private FunctionFixer               functionFixer;
+    private FunctionResolver            functionResolver;
     private ClassFieldExtractorCache    classFieldExtractorCache;
 
     /**
@@ -91,7 +96,7 @@
               null );
     }
 
-    public PackageBuilder(PackageBuilderConfiguration configuration) {
+    public PackageBuilder(final PackageBuilderConfiguration configuration) {
         this( null,
               configuration );
     }
@@ -148,7 +153,8 @@
         try {
             xmlReader.read( reader );
         } catch ( final SAXException e ) {
-            throw new DroolsParserException( e.toString(), e.getCause() );
+            throw new DroolsParserException( e.toString(),
+                                             e.getCause() );
         }
 
         addPackage( xmlReader.getPackageDescr() );
@@ -219,10 +225,10 @@
     }
 
     private void validateUniqueRuleNames(final PackageDescr packageDescr) {
-        Set names = new HashSet();
-        for ( Iterator iter = packageDescr.getRules().iterator(); iter.hasNext(); ) {
-            RuleDescr rule = (RuleDescr) iter.next();
-            String name = rule.getName();
+        final Set names = new HashSet();
+        for ( final Iterator iter = packageDescr.getRules().iterator(); iter.hasNext(); ) {
+            final RuleDescr rule = (RuleDescr) iter.next();
+            final String name = rule.getName();
             if ( names.contains( name ) ) {
                 this.results.add( new ParserError( "Duplicate rule name: " + name,
                                                    rule.getLine(),
@@ -251,6 +257,10 @@
             pkg.addImport( (String) it.next() );
         }
 
+        for ( final Iterator it = packageDescr.getFunctionImports().iterator(); it.hasNext(); ) {
+            pkg.addFunctionImport( (String) it.next() );
+        }
+
         final TypeResolver typeResolver = new ClassTypeResolver( imports,
                                                                  pkg.getPackageCompilationData().getClassLoader() );
 
@@ -280,9 +290,9 @@
     private void addClassCompileTask(final String className,
                                      final String text,
                                      final MemoryResourceReader src,
-                                     ErrorHandler handler) {
+                                     final ErrorHandler handler) {
 
-        String fileName = className.replace( '.',
+        final String fileName = className.replace( '.',
                                              '/' ) + ".java";
         src.add( fileName,
                  text.getBytes() );
@@ -294,6 +304,8 @@
 
     private void addFunction(final FunctionDescr functionDescr) {
         final FunctionBuilder buidler = new FunctionBuilder();
+        this.pkg.addFunction( functionDescr.getName() );
+            
         addClassCompileTask( this.pkg.getName() + "." + ucFirst( functionDescr.getName() ),
                              buidler.build( this.pkg,
                                             functionDescr ),
@@ -304,16 +316,16 @@
     }
 
     private void addFactTemplate(final FactTemplateDescr factTemplateDescr) {
-        List fields = new ArrayList();
+        final List fields = new ArrayList();
         int index = 0;
         for ( final Iterator it = factTemplateDescr.getFields().iterator(); it.hasNext(); ) {
-            FieldTemplateDescr fieldTemplateDescr = (FieldTemplateDescr) it.next();
+            final FieldTemplateDescr fieldTemplateDescr = (FieldTemplateDescr) it.next();
             FieldTemplate fieldTemplate = null;
             try {
                 fieldTemplate = new FieldTemplateImpl( fieldTemplateDescr.getName(),
                                                        index++,
                                                        getTypeResolver().resolveType( fieldTemplateDescr.getClassType() ) );
-            } catch ( ClassNotFoundException e ) {
+            } catch ( final ClassNotFoundException e ) {
                 this.results.add( new FieldTemplateError( this.pkg,
                                                           fieldTemplateDescr,
                                                           null,
@@ -322,7 +334,7 @@
             fields.add( fieldTemplate );
         }
 
-        FactTemplate factTemplate = new FactTemplateImpl( this.pkg,
+        final FactTemplate factTemplate = new FactTemplateImpl( this.pkg,
                                                           factTemplateDescr.getName(),
                                                           (FieldTemplate[]) fields.toArray( new FieldTemplate[fields.size()] ) );
     }
@@ -336,7 +348,8 @@
         ruleDescr.setClassName( ucFirst( ruleClassName ) );
 
         final RuleBuilder builder = new RuleBuilder( getTypeResolver(),
-                                                     classFieldExtractorCache );
+                                                     getFunctionFixer(),
+                                                     this.classFieldExtractorCache );
 
         builder.build( this.pkg,
                        ruleDescr );
@@ -361,15 +374,31 @@
      */
     private TypeResolver getTypeResolver() {
         if ( this.typeResolver == null ) {
-            typeResolver = new ClassTypeResolver( pkg.getImports(),
-                                                  pkg.getPackageCompilationData().getClassLoader() );
+            this.typeResolver = new ClassTypeResolver( this.pkg.getImports(),
+                                                       this.pkg.getPackageCompilationData().getClassLoader() );
             // make an automatic import for the current package
-            typeResolver.addImport( pkg.getName() + ".*" );
-            typeResolver.addImport( "java.lang.*" );
+            this.typeResolver.addImport( this.pkg.getName() + ".*" );
+            this.typeResolver.addImport( "java.lang.*" );
         }
         return this.typeResolver;
     }
 
+    private FunctionResolver getFunctionResolver() {
+        if ( this.functionResolver == null ) {
+            this.functionResolver = new StaticMethodFunctionResolver( this.pkg.getFunctionImports(),
+                                                                      getTypeResolver() );
+        }
+
+        return this.functionResolver;
+    }
+    
+    private FunctionFixer getFunctionFixer() {
+        if ( this.functionFixer == null ) {
+            this.functionFixer = new FunctionFixer(this.pkg, getFunctionResolver() );
+        }
+        return this.functionFixer;
+    }
+
     /**
      * This will setup the semantic components of the rule for compiling later on.
      * It will not actually call the compiler
@@ -430,30 +459,30 @@
      * code.
      */
     private void compileAll() {
-        String[] classes = new String[this.generatedClassList.size()];
+        final String[] classes = new String[this.generatedClassList.size()];
         this.generatedClassList.toArray( classes );
 
         final CompilationResult result = this.compiler.compile( classes,
-                                                                src,
+                                                                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++ ) {
-                CompilationProblem err = result.getErrors()[i];
+                final CompilationProblem err = result.getErrors()[i];
 
-                ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
+                final ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
                 if ( handler instanceof RuleErrorHandler ) {
-                    RuleErrorHandler rh = (RuleErrorHandler) handler;
+                    final RuleErrorHandler rh = (RuleErrorHandler) handler;
 
                 }
                 handler.addError( err );
             }
 
-            Collection errors = this.errorHandlers.values();
-            for ( Iterator iter = errors.iterator(); iter.hasNext(); ) {
-                ErrorHandler handler = (ErrorHandler) iter.next();
+            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() );
@@ -530,20 +559,22 @@
     }
 
     private void loadCompiler() {
-        switch ( configuration.getCompiler() ) {
+        switch ( this.configuration.getCompiler() ) {
             case PackageBuilderConfiguration.JANINO : {
-                if ( !"1.4".equals( configuration.getJavaLanguageLevel() ) ) throw new RuntimeDroolsException( "Incompatible Java language level with selected compiler" );
-                compiler = JavaCompilerFactory.getInstance().createCompiler( "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 : {
-                EclipseJavaCompilerSettings eclipseSettings = new EclipseJavaCompilerSettings();
+                final EclipseJavaCompilerSettings eclipseSettings = new EclipseJavaCompilerSettings();
                 eclipseSettings.getMap().put( "org.eclipse.jdt.core.compiler.codegen.targetPlatform",
-                                              configuration.getJavaLanguageLevel() );
+                                              this.configuration.getJavaLanguageLevel() );
                 eclipseSettings.getMap().put( "org.eclipse.jdt.core.compiler.source",
-                                              configuration.getJavaLanguageLevel() );
-                compiler = new EclipseJavaCompiler( eclipseSettings );
+                                              this.configuration.getJavaLanguageLevel() );
+                this.compiler = new EclipseJavaCompiler( eclipseSettings );
                 break;
             }
         }
@@ -575,16 +606,16 @@
      * that originally spawned the code to be compiled.
      */
     public abstract static class ErrorHandler {
-        private List     errors  = new ArrayList();
+        private final List     errors  = new ArrayList();
         protected String message;
         private boolean  inError = false;
 
         /** This needes to be checked if there is infact an error */
         public boolean isInError() {
-            return inError;
+            return this.inError;
         }
 
-        public void addError(CompilationProblem err) {
+        public void addError(final CompilationProblem err) {
             this.errors.add( err );
             this.inError = true;
         }
@@ -603,11 +634,11 @@
          * Its not 1 to 1 with reported errors.
          */
         protected CompilationProblem[] collectCompilerProblems() {
-            if ( errors.size() == 0 ) {
+            if ( this.errors.size() == 0 ) {
                 return null;
             } else {
-                CompilationProblem[] list = new CompilationProblem[errors.size()];
-                errors.toArray( list );
+                final CompilationProblem[] list = new CompilationProblem[this.errors.size()];
+                this.errors.toArray( list );
                 return list;
             }
         }
@@ -618,19 +649,19 @@
         private PatternDescr descr;
         private Rule         rule;
 
-        public RuleErrorHandler(PatternDescr ruleDescr,
-                                Rule rule,
-                                String message) {
+        public RuleErrorHandler(final PatternDescr ruleDescr,
+                                final Rule rule,
+                                final String message) {
             this.descr = ruleDescr;
             this.rule = rule;
             this.message = message;
         }
 
         public DroolsError getError() {
-            return new RuleError( rule,
-                                  descr,
+            return new RuleError( this.rule,
+                                  this.descr,
                                   collectCompilerProblems(),
-                                  message );
+                                  this.message );
         }
 
     }
@@ -641,9 +672,9 @@
      */
     public static class RuleInvokerErrorHandler extends RuleErrorHandler {
 
-        public RuleInvokerErrorHandler(PatternDescr ruleDescr,
-                                       Rule rule,
-                                       String message) {
+        public RuleInvokerErrorHandler(final PatternDescr ruleDescr,
+                                       final Rule rule,
+                                       final String message) {
             super( ruleDescr,
                    rule,
                    message );
@@ -654,20 +685,20 @@
 
         private FunctionDescr descr;
 
-        public FunctionErrorHandler(FunctionDescr functionDescr,
-                                    String message) {
+        public FunctionErrorHandler(final FunctionDescr functionDescr,
+                                    final String message) {
             this.descr = functionDescr;
             this.message = message;
         }
 
         public DroolsError getError() {
-            return new FunctionError( descr,
+            return new FunctionError( this.descr,
                                       collectCompilerProblems(),
-                                      message );
+                                      this.message );
         }
 
     }
 
-    private static JavaCompiler cachedJavaCompiler = null;
+    private static final JavaCompiler cachedJavaCompiler = null;
 
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/FunctionFixer.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/FunctionFixer.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/FunctionFixer.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -21,6 +21,9 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.drools.spi.FunctionResolver;
+import org.drools.rule.Package;
+
 /**
  * This horrific utility adds in the function class name (which is the same as the functions method name)
  * into the RHS guts of a rule. It has to tip toe around method calls, new declarations and other 
@@ -35,10 +38,20 @@
  */
 public class FunctionFixer {
 
-    static Pattern   FUNCTION = Pattern.compile( "(\\S*\\s*|\\.\\s*)\\b([\\S&&[^\\.\\(\\)]]+)\\s*\\(([^)]*)\\)",
-                                                 Pattern.DOTALL );
-    static final Set KEYWORDS = getJavaKeywords();
+    static Pattern                 FUNCTION = Pattern.compile( "(\\S*\\s*|\\.\\s*)\\b([\\S&&[^\\.\\(\\)]]+)\\s*\\(([^)]*)\\)",
+                                                               Pattern.DOTALL );
+    static final Set               KEYWORDS = getJavaKeywords();
 
+    private final FunctionResolver resolver;
+
+    private final Package          pkg;
+
+    public FunctionFixer(Package pkg,
+                         FunctionResolver resolver) {
+        this.resolver = resolver;
+        this.pkg = pkg;
+    }
+
     public String fix(final String raw) {
         //return raw;
         return fix( raw,
@@ -59,7 +72,7 @@
             // instead of just using matcher.end(), grow the endIndex
             // as necessary to close all '(' in the matched String
             final int endIndex = findEndParenthesis( raw,
-                                               matcher );
+                                                     matcher );
             if ( endIndex < 0 ) {
                 // this means that the first '(' is inside quotes - jump it and try again
                 startIndex = matcher.start( 3 );
@@ -95,13 +108,22 @@
                 function = matcher.group( 2 ).trim();
                 // if we have a reserved work, DO NOT TOUCH !
                 // if we have no function name, DO NOT TOUCH !
-                if ( function == null ||
-                        function.length() == 0 ||
-                        FunctionFixer.KEYWORDS.contains( function )  ) {
+                if ( function == null || function.length() == 0 || FunctionFixer.KEYWORDS.contains( function ) ) {
                     function = raw.substring( matcher.start( 2 ),
                                               matcher.start( 3 ) - 1 );
                 } else {
-                    function = ucFirst( function ) + "." + function;
+                    int countParams = 0;
+                    for ( int i = 0, length = params.length(); i < length; i++ ) {
+                        if ( params.charAt( i ) == ',' ) {
+                            countParams++;
+                        }
+                    }
+                    if ( this.pkg.getFunctions().contains( function ) ) {
+                        function = ucFirst( function ) + "." + function;
+                    } else {
+                        function = resolver.resolveFunction( function,
+                                                             countParams + 1 ) + "." + function;
+                    }
                 }
             }
 

Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -29,7 +29,6 @@
 import org.antlr.stringtemplate.StringTemplateGroup;
 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
 import org.drools.RuntimeDroolsException;
-import org.drools.base.ClassFieldExtractor;
 import org.drools.base.ClassFieldExtractorCache;
 import org.drools.base.ClassObjectType;
 import org.drools.base.FieldFactory;
@@ -56,11 +55,9 @@
 import org.drools.lang.descr.DeclarativeInvokerDescr;
 import org.drools.lang.descr.EvalDescr;
 import org.drools.lang.descr.ExistsDescr;
-import org.drools.lang.descr.FieldAccessDescr;
 import org.drools.lang.descr.FieldBindingDescr;
 import org.drools.lang.descr.FieldConstraintDescr;
 import org.drools.lang.descr.FromDescr;
-import org.drools.lang.descr.FunctionCallDescr;
 import org.drools.lang.descr.LiteralRestrictionDescr;
 import org.drools.lang.descr.MethodAccessDescr;
 import org.drools.lang.descr.NotDescr;
@@ -97,7 +94,6 @@
 import org.drools.rule.VariableRestriction;
 import org.drools.spi.DataProvider;
 import org.drools.spi.Evaluator;
-import org.drools.spi.Extractor;
 import org.drools.spi.FieldExtractor;
 import org.drools.spi.FieldValue;
 import org.drools.spi.ObjectType;
@@ -143,16 +139,19 @@
                                                                                               AngleBracketTemplateLexer.class );
 
     private static final KnowledgeHelperFixer knowledgeHelperFixer = new KnowledgeHelperFixer();
-    private static final FunctionFixer        functionFixer        = new FunctionFixer();
+    
+    private final FunctionFixer               functionFixer;
 
     // @todo move to an interface so it can work as a decorator
     private final JavaExprAnalyzer            analyzer             = new JavaExprAnalyzer();
     private ClassFieldExtractorCache          classFieldExtractorCache;
 
-    public RuleBuilder(TypeResolver resolver,
-                       ClassFieldExtractorCache cache) {
+    public RuleBuilder(final TypeResolver typeResolver,
+                       final FunctionFixer functionFixer,
+                       final ClassFieldExtractorCache cache) {
         this.classFieldExtractorCache = cache;
-        this.typeResolver = resolver;
+        this.typeResolver = typeResolver;
+        this.functionFixer = functionFixer;
         this.errors = new ArrayList();
     }
 
@@ -410,7 +409,7 @@
 
         ObjectType objectType = null;
 
-        FactTemplate factTemplate = this.pkg.getFactTemplate( columnDescr.getObjectType() );
+        final FactTemplate factTemplate = this.pkg.getFactTemplate( columnDescr.getObjectType() );
 
         if ( factTemplate != null ) {
             objectType = new FactTemplateObjectType( factTemplate );
@@ -477,7 +476,7 @@
         if ( fieldConstraintDescr.getRestrictions().size() == 1 ) {
             final Object object = fieldConstraintDescr.getRestrictions().get( 0 );
 
-            Restriction restriction = buildRestriction( extractor,
+            final Restriction restriction = buildRestriction( extractor,
                                                         fieldConstraintDescr,
                                                         (RestrictionDescr) object );
             if ( restriction == null ) {
@@ -499,7 +498,7 @@
             return;
         }
 
-        List orList = new ArrayList();
+        final List orList = new ArrayList();
         List andList = null;
 
         RestrictionDescr currentRestriction = null;
@@ -509,7 +508,7 @@
         List previousList = null;
 
         for ( final Iterator it = fieldConstraintDescr.getRestrictions().iterator(); it.hasNext(); ) {
-            Object object = it.next();
+            final Object object = it.next();
 
             // Process an and/or connective 
             if ( object instanceof RestrictionConnectiveDescr ) {
@@ -550,7 +549,7 @@
                                 // Can't have an 'and' connective with one child, so add directly to the or list
                                 orList.add( andList.get( 0 ) );
                             } else {
-                                Restriction restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
+                                final Restriction restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
                                 orList.add( restrictions );
                             }
                             andList = null;
@@ -568,7 +567,7 @@
             currentRestriction = (RestrictionDescr) object;
         }
 
-        Restriction restriction = buildRestriction( extractor,
+        final Restriction restriction = buildRestriction( extractor,
                                                     fieldConstraintDescr,
                                                     currentRestriction );
         currentList.add( restriction );
@@ -599,9 +598,9 @@
                                                                    restrictions ) );
     }
 
-    private Restriction buildRestriction(FieldExtractor extractor,
-                                         FieldConstraintDescr fieldConstraintDescr,
-                                         RestrictionDescr restrictionDescr) {
+    private Restriction buildRestriction(final FieldExtractor extractor,
+                                         final FieldConstraintDescr fieldConstraintDescr,
+                                         final RestrictionDescr restrictionDescr) {
         Restriction restriction = null;
         if ( restrictionDescr instanceof LiteralRestrictionDescr ) {
             restriction = buildRestriction( extractor,
@@ -765,7 +764,7 @@
         st.setAttribute( "methodName",
                          className );
 
-        final String returnValueText = RuleBuilder.functionFixer.fix( returnValueRestrictionDescr.getText() );
+        final String returnValueText = this.functionFixer.fix( returnValueRestrictionDescr.getText() );
         st.setAttribute( "text",
                          returnValueText );
 
@@ -857,7 +856,7 @@
         st.setAttribute( "methodName",
                          className );
 
-        final String predicateText = RuleBuilder.functionFixer.fix( predicateDescr.getText() );
+        final String predicateText = this.functionFixer.fix( predicateDescr.getText() );
         st.setAttribute( "text",
                          predicateText );
 
@@ -897,20 +896,20 @@
                                predicateDescr );
     }
 
-    private From build(FromDescr fromDescr) {
-        Column column = build( fromDescr.getReturnedColumn() );
+    private From build(final FromDescr fromDescr) {
+        final Column column = build( fromDescr.getReturnedColumn() );
 
-        DeclarativeInvokerDescr invokerDescr = fromDescr.getDataSource();
+        final DeclarativeInvokerDescr invokerDescr = fromDescr.getDataSource();
 
         DataProvider dataProvider = null;
 
         if ( invokerDescr.getClass() == MethodAccessDescr.class ) {
-            MethodAccessDescr methodAccessor = (MethodAccessDescr) invokerDescr;
+            final MethodAccessDescr methodAccessor = (MethodAccessDescr) invokerDescr;
 
             ValueHandler instanceValueHandler = null;
-            String variableName = methodAccessor.getVariableName();
-            if ( declarations.containsKey( variableName ) ) {
-                instanceValueHandler = new DeclarationVariable( (Declaration) declarations.get( variableName ) );
+            final String variableName = methodAccessor.getVariableName();
+            if ( this.declarations.containsKey( variableName ) ) {
+                instanceValueHandler = new DeclarationVariable( (Declaration) this.declarations.get( variableName ) );
             } else if ( this.pkg.getGlobals().containsKey( variableName ) ) {
                 instanceValueHandler = new GlobalVariable( variableName,
                                                            (Class) this.pkg.getGlobals().get( variableName ) );
@@ -918,10 +917,10 @@
                 throw new IllegalArgumentException( "The variable name [" + variableName + "] was not a global or declaration." );
             }
 
-            List arguments = ((MethodAccessDescr) invokerDescr).getArguments();
-            List valueHandlers = new ArrayList();
+            final List arguments = ((MethodAccessDescr) invokerDescr).getArguments();
+            final List valueHandlers = new ArrayList();
 
-            for ( Iterator iter = arguments.iterator(); iter.hasNext(); ) {
+            for ( final Iterator iter = arguments.iterator(); iter.hasNext(); ) {
                 valueHandlers.add( buildValueHandler( (ArgumentValueDescr) iter.next() ) );
                 //                if ( desc.getType() == ArgumentValueDescr.VARIABLE ) {
                 //                    if ( this.declarations.containsKey( desc.getValue() ) ) {
@@ -939,7 +938,7 @@
                 //                }
             }
 
-            MethodInvoker invoker = new MethodInvoker( methodAccessor.getMethodName(),
+            final MethodInvoker invoker = new MethodInvoker( methodAccessor.getMethodName(),
                                                        instanceValueHandler,
                                                        (ValueHandler[]) valueHandlers.toArray( new ValueHandler[valueHandlers.size()] ) );
             dataProvider = new MethodDataProvider( invoker );
@@ -961,11 +960,11 @@
                          dataProvider );
     }
 
-    private ValueHandler buildValueHandler(ArgumentValueDescr descr) {
+    private ValueHandler buildValueHandler(final ArgumentValueDescr descr) {
         ValueHandler valueHandler = null;
         if ( descr.getType() == ArgumentValueDescr.VARIABLE ) {
             if ( this.declarations.containsKey( descr.getValue() ) ) {
-                valueHandler = new DeclarationVariable( (Declaration) declarations.get( descr.getValue() ) );
+                valueHandler = new DeclarationVariable( (Declaration) this.declarations.get( descr.getValue() ) );
             } else if ( this.pkg.getGlobals().containsKey( descr.getValue() ) ) {
                 valueHandler = new GlobalVariable( (String) descr.getValue(),
                                                    (Class) this.pkg.getGlobals().get( descr.getValue() ) );
@@ -973,22 +972,22 @@
                 throw new IllegalArgumentException( "Uknown variable: " + descr.getValue() );
             }
         } else if ( descr.getType() == ArgumentValueDescr.MAP ) {
-            ArgumentValueDescr.KeyValuePairDescr[] pairs = (ArgumentValueDescr.KeyValuePairDescr[]) descr.getValue();
-            List list = new ArrayList( pairs.length );
+            final ArgumentValueDescr.KeyValuePairDescr[] pairs = (ArgumentValueDescr.KeyValuePairDescr[]) descr.getValue();
+            final List list = new ArrayList( pairs.length );
             for ( int i = 0, length = pairs.length; i < length; i++ ) {
                 list.add( new MapValue.KeyValuePair( buildValueHandler( pairs[i].getKey() ),
                                                      buildValueHandler( pairs[i].getValue() ) ) );
             }
 
             valueHandler = new MapValue( (MapValue.KeyValuePair[]) list.toArray( new MapValue.KeyValuePair[pairs.length] ) );
-        } else if (descr.getType() == ArgumentValueDescr.LIST ) {
-          List args = (List) descr.getValue();
-          List handlers = new ArrayList(args.size());
-          for ( Iterator iter = args.iterator(); iter.hasNext(); ) {
-            ArgumentValueDescr arg = (ArgumentValueDescr) iter.next();
-            handlers.add( buildValueHandler( arg ) );
-          }
-          valueHandler = new ListValue(handlers);
+        } else if ( descr.getType() == ArgumentValueDescr.LIST ) {
+            final List args = (List) descr.getValue();
+            final List handlers = new ArrayList( args.size() );
+            for ( final Iterator iter = args.iterator(); iter.hasNext(); ) {
+                final ArgumentValueDescr arg = (ArgumentValueDescr) iter.next();
+                handlers.add( buildValueHandler( arg ) );
+            }
+            valueHandler = new ListValue( handlers );
         } else {
             // handling a literal
             valueHandler = new LiteralValue( (String) descr.getValue(),
@@ -1022,7 +1021,7 @@
         st.setAttribute( "methodName",
                          className );
 
-        final String evalText = RuleBuilder.functionFixer.fix( evalDescr.getText() );
+        final String evalText = this.functionFixer.fix( evalDescr.getText() );
         st.setAttribute( "text",
                          evalText );
 
@@ -1080,7 +1079,7 @@
                                      (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
                                      ruleDescr.getConsequence() );
         st.setAttribute( "text",
-                         RuleBuilder.functionFixer.fix( RuleBuilder.knowledgeHelperFixer.fix( ruleDescr.getConsequence() ) ) );
+                         this.functionFixer.fix( RuleBuilder.knowledgeHelperFixer.fix( ruleDescr.getConsequence() ) ) );
 
         this.methods.add( st.toString() );
 
@@ -1143,7 +1142,7 @@
         }
 
         buffer.append( "public class " + ucFirst( this.ruleDescr.getClassName() ) + " {" + lineSeparator );
-        buffer.append( "    private static final long serialVersionUID  = 7952983928232702826L;" + lineSeparator );
+        buffer.append( "    private static final long serialVersionUID  = 320L;" + lineSeparator );
 
         for ( int i = 0, size = this.methods.size() - 1; i < size; i++ ) {
             buffer.append( this.methods.get( i ) + lineSeparator );
@@ -1199,12 +1198,12 @@
 
         if ( objectType.getValueType() == ValueType.FACTTEMPLATE_TYPE ) {
             //@todo use extractor cache            
-            FactTemplate factTemplate = ((FactTemplateObjectType) objectType).getFactTemplate();
+            final FactTemplate factTemplate = ((FactTemplateObjectType) objectType).getFactTemplate();
             extractor = new FactTemplateFieldExtractor( factTemplate,
                                                         factTemplate.getFieldTemplateIndex( fieldName ) );
         } else {
             try {
-                extractor = classFieldExtractorCache.getExtractor( ((ClassObjectType) objectType).getClassType(),
+                extractor = this.classFieldExtractorCache.getExtractor( ((ClassObjectType) objectType).getClassType(),
                                                                    fieldName );
             } catch ( final RuntimeDroolsException e ) {
                 this.errors.add( new RuleError( this.rule,

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/StaticMethodFunctionResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/StaticMethodFunctionResolver.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/StaticMethodFunctionResolver.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,73 @@
+package org.drools.semantics.java;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.xpath.functions.FuncId;
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FunctionResolver;
+import org.drools.spi.TypeResolver;
+
+public class StaticMethodFunctionResolver
+    implements
+    FunctionResolver {
+
+    private final List         functionImports;
+
+    private final TypeResolver typeResolver;
+
+    public StaticMethodFunctionResolver(final List imports,
+                                        final TypeResolver typeResolver) {
+        this.functionImports = imports;
+
+        this.typeResolver = typeResolver;
+    }
+
+    public void addFunctionImport(String functionImport) {
+        this.functionImports.add( functionImport );
+
+    }
+
+    public List getFunctionImports() {
+        return this.functionImports;
+    }
+
+    public String resolveFunction(String functionName,
+                                  int numberOfArgs) {
+        for ( Iterator it = this.functionImports.iterator(); it.hasNext(); ) {
+            String functionImport = (String) it.next();
+
+            // find the last '.' so we can separte the method/* from the package and Class
+            int lastDot = functionImport.lastIndexOf( '.' );
+            String name = functionImport.substring( lastDot );
+
+            // if a functionImport imports the function name directly, i.e not using *, then only go further if they match.
+            if ( !name.endsWith( "*" ) && !!functionName.equals( name ) ) {
+                continue;
+            }
+
+            Class clazz;
+            try {
+                clazz = typeResolver.resolveType( functionImport.substring( 0,
+                                                                            lastDot ) );
+            } catch ( ClassNotFoundException e ) {
+                // todo : must be a better way so we don't have to try/catch each resolveType call
+                throw new RuntimeDroolsException( e );
+            }
+            Method[] methods = clazz.getMethods();
+            for ( int i = 0, length = methods.length; i < length; i++ ) {
+                if ( (methods[i].getModifiers() & Modifier.STATIC) == Modifier.STATIC && (methods[i].getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC && methods[i].getName().equals( functionName )
+                     && methods[i].getParameterTypes().length == numberOfArgs ) {
+                    return clazz.getName().replace( '$',
+                                                    '.' );
+                }
+            }
+        }
+        throw new RuntimeDroolsException( "unable to find the function '" + functionName + "'" );
+    }
+
+}

Added: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Func.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Func.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Func.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,15 @@
+package org.drools;
+
+public class Func {
+    public static void func() {
+        
+    }
+    
+    public static void func(String string) {
+        
+    }
+    
+    public static void func(String x, String y) {
+        
+    }    
+}

Added: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,13 @@
+package org.drools;
+
+public class StaticMethods {
+    
+    public static String getString1(String string) {
+        return string;
+    }
+    
+    public static String getString2(String string) {
+        return string;
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods2.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods2.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/StaticMethods2.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,7 @@
+package org.drools;
+
+public class StaticMethods2 {    
+    public static String getString3(String string, Integer integer) {
+        return string + integer;
+    }    
+}

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/IntegrationCases.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/IntegrationCases.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/IntegrationCases.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -796,7 +796,29 @@
         assertEquals( 1,
                       list.size() );
     }
+    
+    public void testImportFunctions() throws Exception {
+        final PackageBuilder builder = new PackageBuilder();
+        builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_ImportFunctions.drl" ) ) );
+        final Package pkg = builder.getPackage();
 
+        final RuleBase ruleBase = getRuleBase();
+        ruleBase.addPackage( pkg );
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        Cheese cheese = new Cheese( "stilton", 15 );
+        workingMemory.assertObject( cheese );
+        List list = new ArrayList();
+        workingMemory.setGlobal( "list", list );        
+        workingMemory.fireAllRules();
+        
+        assertEquals( 4, list.size() );
+        
+        assertEquals( "rule1", list.get( 0 ) );
+        assertEquals( "rule2", list.get( 1 ) );
+        assertEquals( "rule3", list.get( 2 ) );
+        assertEquals( "rule4", list.get( 3 ) );        
+    }
+
     
     public void testBasicFrom() throws Exception {
         final PackageBuilder builder = new PackageBuilder();

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/FunctionFixerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/FunctionFixerTest.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/FunctionFixerTest.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -16,98 +16,103 @@
  * limitations under the License.
  */
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.spi.TypeResolver;
+import org.drools.rule.Package;
+
 import junit.framework.TestCase;
 
 public class FunctionFixerTest extends TestCase {
 
-    private static final FunctionFixer fixer = new FunctionFixer();
+    private FunctionFixer fixer;
+    
+    public void setUp() {
+        List list = new ArrayList();
+        list.add( "org.drools.*" );
+        TypeResolver typeResolver = new ClassTypeResolver( list );
+        Package pkg = new Package("testPackage");
+        pkg.addFunction( "addFive" );
+        pkg.addFunction( "foo" );
+        pkg.addFunction( "bar" );
+        
+        list = new ArrayList();
+        list.add( "Func.*" );
+        this.fixer = new FunctionFixer( pkg, new StaticMethodFunctionResolver(list, typeResolver) );
+    }
 
     public void testSimple() {
-        final FunctionFixer fixer = new FunctionFixer();
-        assertEquals( "Func.func()",
+        assertEquals( "org.drools.Func.func()",
                       fixer.fix( "func( )" ) );
     }
 
     public void testSimpleWithPArams() {
-        final FunctionFixer fixer = new FunctionFixer();
-        assertEquals( "Func.func(yyy, iii)",
+        assertEquals( "org.drools.Func.func(yyy, iii)",
                       fixer.fix( "func(yyy, iii)" ) );
     }
 
     public void testMoreComplex() {
-        final FunctionFixer fixer = new FunctionFixer();
-        assertEquals( "xxx Func.func(yyy, iii) yyy",
+        assertEquals( "xxx org.drools.Func.func(yyy, iii) yyy",
                       fixer.fix( "xxx func(yyy, iii) yyy" ) );
     }
 
     public void testLeaveAloneNew() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "new Integer (5)",
                       fixer.fix( "new Integer (5)" ) );
     }
 
     public void testLeaveAloneDrools() {
-        final FunctionFixer fixer = new FunctionFixer();
-        assertEquals( "xxx drools.org(iii) Func.func(yyy, iii) yyy",
+        assertEquals( "xxx drools.org(iii) org.drools.Func.func(yyy, iii) yyy",
                       fixer.fix( "xxx drools.org(iii) func(yyy, iii) yyy" ) );
     }
 
-    public void testWorkWithDotAll() {
-        final FunctionFixer fixer = new FunctionFixer();
+    public void testWorkWithDotAll() {        
         assertEquals( "\n\t\n\tAddFive.addFive(list) ;",
                       fixer.fix( "\n\t\n\taddFive ( list ) ;" ) );
     }
 
     public void testWithDollarSigns() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "\nFoo.foo($list);",
                       fixer.fix( "\nfoo($list);" ) );
     }
 
     public void testReservedWordsInJava() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "\nfor(int i=0; i < 2; i++) { /*do noithing*/ }",
                       fixer.fix( "\nfor(int i=0; i < 2; i++) { /*do noithing*/ }" ) );
     }
 
     public void testMultipleInABracket() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "if (Foo.foo(bar)) { Bar.bar(baz); }",
                       fixer.fix( "if (foo(bar)) { bar(baz); }" ) );
     }
 
     public void testInBrackets() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "if (Foo.foo(bar))",
                       fixer.fix( "if (foo(bar))" ) );
     }
 
     public void testAlreadyAdded() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "Foo.foo(bar)",
                       fixer.fix( "Foo.foo(bar)" ) );
     }
 
     public void testInString() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "\"if (foo(bar))\"",
                       fixer.fix( "\"if (foo(bar))\"" ) );
     }
 
     public void testComplexWithBrackets() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "System.out.println(\"foo(\" + Foo.foo(bar) + Bar.bar(baz)",
                       fixer.fix( "System.out.println(\"foo(\" + foo(bar) + bar(baz)" ) );
     }
     
     public void testXPath() {
-        final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "foo.executeXpath(\"//node1/node2/text()\")",
                       fixer.fix("foo.executeXpath(\"//node1/node2/text()\")" ) );
       }
       
       public void testExpressionGrouping() {
-       final FunctionFixer fixer = new FunctionFixer();
         assertEquals( "while((foo = bar.baz()) != null)",
                       fixer.fix( "while((foo = bar.baz()) != null)" ) );
       }     

Added: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/StaticMethodFunctionResolverTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/StaticMethodFunctionResolverTest.java	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/semantics/java/StaticMethodFunctionResolverTest.java	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,26 @@
+package org.drools.semantics.java;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.spi.FunctionResolver;
+import org.drools.spi.TypeResolver;
+
+import junit.framework.TestCase;
+
+public class StaticMethodFunctionResolverTest extends TestCase {
+    public void test1() {                
+        List list = new ArrayList();
+        list.add( "org.drools.StaticMethods" );        
+        TypeResolver typeResolver = new ClassTypeResolver( list );
+        
+        
+        list = new ArrayList();
+        list.add( "StaticMethods.*" );
+        FunctionResolver functionResolver = new StaticMethodFunctionResolver( list, typeResolver );
+        
+        System.out.println( functionResolver.resolveFunction( "getString", 1 ) );
+        
+        
+    }
+}

Added: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ImportFunctions.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ImportFunctions.drl	2006-08-31 16:26:48 UTC (rev 6044)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ImportFunctions.drl	2006-08-31 16:53:31 UTC (rev 6045)
@@ -0,0 +1,45 @@
+package org.drools.test;
+
+import function org.drools.StaticMethods.*;
+import function org.drools.StaticMethods2.getString3;
+
+import org.drools.Cheese;
+
+global java.util.List list;
+
+function String getString4( String string ) {
+    return string;
+}
+
+rule "test rule1"
+	salience 30
+    when
+        Cheese()
+    then
+		list.add( getString1( "rule1" ) );
+end    
+
+rule "test rule2"
+	salience 20
+    when
+        Cheese( type == ( getString2("stilton") ) );
+    then
+		list.add( getString3( "rule", new Integer( 2 ) ) );
+end    
+
+rule "test rule3"
+	salience 10
+    when
+        Cheese( $type : type);
+        eval( $type.equals( getString1( "stilton" ) ) );
+    then
+		list.add( getString2( "rule3" ) );
+end    
+
+rule "test rule4"
+	salience 0
+    when
+        Cheese();
+    then
+		list.add( getString4( "rule4" ) );
+end    
\ No newline at end of file




More information about the jboss-svn-commits mailing list