[jboss-svn-commits] JBL Code SVN: r20072 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests and 8 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon May 19 21:53:38 EDT 2008
Author: tirelli
Date: 2008-05-19 21:53:38 -0400 (Mon, 19 May 2008)
New Revision: 20072
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java
Modified:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockRuleBase.java
labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessor.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/DialectDatas.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/TypeDeclaration.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java
Log:
Fixing bean generation
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 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -16,8 +16,10 @@
* limitations under the License.
*/
+import java.beans.IntrospectionException;
import java.io.IOException;
import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
@@ -25,7 +27,10 @@
import java.util.Map;
import java.util.Set;
+import org.drools.base.ClassFieldAccessor;
import org.drools.base.ClassFieldAccessorCache;
+import org.drools.base.ClassFieldReader;
+import org.drools.base.ClassFieldWriter;
import org.drools.base.ClassTypeResolver;
import org.drools.base.TypeResolver;
import org.drools.commons.jci.problems.CompilationProblem;
@@ -52,6 +57,7 @@
import org.drools.process.core.Process;
import org.drools.rule.CompositePackageClassLoader;
import org.drools.rule.ImportDeclaration;
+import org.drools.rule.JavaDialectData;
import org.drools.rule.MapBackedClassLoader;
import org.drools.rule.Package;
import org.drools.rule.Rule;
@@ -454,10 +460,19 @@
try {
if (typeDescr.getFields().size() > 0) {
//generate the bean if its needed
- generateDeclaredBean(typeDescr);
+ generateDeclaredBean(typeDescr, type);
}
clazz = typeResolver.resolveType( className );
type.setTypeClass( clazz );
+ if( type.getTypeClassDef() != null ) {
+ try {
+ buildFieldAccessors( type );
+ } catch ( Exception e ) {
+ this.results.add( new TypeDeclarationError( "Error creating field accessors for '" + className + "' for type '" + type.getTypeName() + "'",
+ typeDescr.getLine() ) );
+ continue;
+ }
+ }
} catch ( final ClassNotFoundException e ) {
this.results.add( new TypeDeclarationError( "Class not found '" + className + "' for type '" + type.getTypeName() + "'",
@@ -484,11 +499,51 @@
}
/**
+ *
+ * @throws SecurityException
+ * @throws IllegalArgumentException
+ * @throws InstantiationException
+ * @throws IllegalAccessException
+ * @throws IOException
+ * @throws IntrospectionException
+ * @throws ClassNotFoundException
+ * @throws NoSuchMethodException
+ * @throws InvocationTargetException
+ * @throws NoSuchFieldException
+ */
+ private final void buildFieldAccessors( final TypeDeclaration type ) throws SecurityException,
+ IllegalArgumentException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException,
+ IntrospectionException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ InvocationTargetException,
+ NoSuchFieldException {
+ ClassFieldAccessorCache cache = ClassFieldAccessorCache.getInstance();
+ ClassDefinition cd = type.getTypeClassDef();
+
+ for ( FieldDefinition attrDef : cd.getFieldsDefinitions() ) {
+ ClassFieldReader reader = cache.getReader( cd.getDefinedClass(),
+ attrDef.getName(),
+ this.pkg.getDialectDatas().getClassLoader() );
+ ClassFieldWriter writer = cache.getWriter( cd.getDefinedClass(),
+ attrDef.getName(),
+ this.pkg.getDialectDatas().getClassLoader() );
+ ClassFieldAccessor accessor = new ClassFieldAccessor( reader,
+ writer );
+ attrDef.setFieldAccessor( accessor );
+ }
+ }
+
+ /**
* Generates a bean, and adds it to the composite class loader that
* everything is using.
*
*/
- private void generateDeclaredBean(TypeDeclarationDescr typeDescr) {
+ private void generateDeclaredBean(TypeDeclarationDescr typeDescr, TypeDeclaration type) {
+ // need to fix classloader?
ClassBuilder cb = new ClassBuilder();
String fullName = this.pkg.getName() + "." + typeDescr.getTypeName();
ClassDefinition def = new ClassDefinition(fullName);
@@ -501,13 +556,15 @@
byte[] d = cb.buildClass(def);
if (this.generatedBeanClassLoader == null) {
+ CompositePackageClassLoader ccl = (CompositePackageClassLoader) this.pkg.getDialectDatas().getClassLoader();
this.generatedBeanClassLoader = new MapBackedClassLoader(this.configuration.getClassLoader());
- CompositePackageClassLoader ccl = (CompositePackageClassLoader) this.pkg.getDialectDatas().getClassLoader();
ccl.addClassLoader(this.generatedBeanClassLoader);
}
- generatedBeanClassLoader.addClass(fullName, d);
+ this.generatedBeanClassLoader.addClass( fullName, d);
+ type.setTypeClassDef( def );
} catch (Exception e) {
- this.results.add(new TypeDeclarationError("Unable to create a class for declared type " + typeDescr.getTypeName(), typeDescr.getLine()));
+ e.printStackTrace();
+ this.results.add(new TypeDeclarationError("Unable to create a class for declared type " + fullName + ": "+e.getMessage()+";", typeDescr.getLine()));
}
}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -16,7 +16,6 @@
* limitations under the License.
*/
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInput;
@@ -105,9 +104,6 @@
import org.drools.event.ObjectRetractedEvent;
import org.drools.event.ObjectUpdatedEvent;
import org.drools.event.WorkingMemoryEventListener;
-import org.drools.factmodel.ClassBuilder;
-import org.drools.factmodel.ClassDefinition;
-import org.drools.factmodel.FieldDefinition;
import org.drools.facttemplates.Fact;
import org.drools.facttemplates.FactTemplate;
import org.drools.lang.DrlDumper;
@@ -115,14 +111,13 @@
import org.drools.lang.descr.PackageDescr;
import org.drools.lang.descr.RuleDescr;
import org.drools.reteoo.ReteooRuleBase;
+import org.drools.rule.FactType;
import org.drools.rule.InvalidRulePackage;
-import org.drools.rule.MapBackedClassLoader;
import org.drools.rule.Package;
import org.drools.rule.builder.dialect.java.JavaDialectConfiguration;
import org.drools.spi.Activation;
import org.drools.spi.ConsequenceExceptionHandler;
import org.drools.spi.GlobalResolver;
-import org.drools.util.DroolsStreamUtils;
import org.drools.xml.XmlDumper;
/** Run all the tests with the ReteOO engine implementation */
@@ -522,55 +517,91 @@
((List) session.getGlobal( "list" )).size() );
}
- public void testGeneratedBeans() throws Exception {
+ public void testGeneratedBeans1() throws Exception {
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_GeneratedBeans.drl" ) ) );
- assertFalse( "" + builder.getErrors(),
+ assertFalse( builder.getErrors().toString(),
builder.hasErrors() );
Package p = builder.getPackage();
assertEquals( 2,
p.getRules().length );
- //to test it we will generate another class that looks just like it
- ClassBuilder cb = new ClassBuilder();
- ClassDefinition def = new ClassDefinition( "org.drools.generatedbeans.Cheese" );
- def.addField( new FieldDefinition( "type",
- "java.lang.String" ) );
- byte[] classdata = cb.buildClass( def );
- MapBackedClassLoader cl = new MapBackedClassLoader( this.getClass().getClassLoader() );
- cl.addClass( "org.drools.generatedbeans.Cheese",
- classdata );
+ // disabling shadow proxies, since they don't work yet with generated facts and
+ // we will scrap shadow proxies in drools 5 anyway.
+ RuleBaseConfiguration conf = new RuleBaseConfiguration();
+ conf.setShadowProxy( false );
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
+ ruleBase.addPackage( p );
- //this one doesn't work
- RuleBase ruleBase = RuleBaseFactory.newRuleBase( new RuleBaseConfiguration( cl ) );
+ // Retrieve the generated fact type
+ FactType cheeseFact = ruleBase.getFactType( "org.drools.generatedbeans.Cheese" );
- //this one does work...
- ruleBase = RuleBaseFactory.newRuleBase( new RuleBaseConfiguration( p.getDialectDatas().getClassLoader() ) );
+ // Create a new Fact instance
+ Object cheese = cheeseFact.newInstance();
- ruleBase.addPackage( p );
+ // Set a field value using the more verbose method chain...
+ // should we add short cuts?
+ cheeseFact.getField( "type" ).getFieldAccessor().setValue( cheese,
+ "stilton" );
- //this one just won't work
- //Class cc = cl.loadClass("org.drools.generatedbeans.Cheese");
+ // just documenting toString() result:
+ assertEquals( "Cheese( type=stilton )",
+ cheese.toString() );
- //this one has an error with shadow proxies unless I use the same classloader as the package...
- Class cc = p.getDialectDatas().getClassLoader().loadClass( "org.drools.generatedbeans.Cheese" );
+ // reading the field attribute, using the method chain
+ assertEquals( "stilton",
+ cheeseFact.getField( "type" ).getFieldAccessor().getValue( cheese ) );
- Object cheese = cc.newInstance();
-
- WorkingMemory wm = ruleBase.newStatefulSession();
+ // creating a stateful session
+ StatefulSession wm = ruleBase.newStatefulSession();
List result = new ArrayList();
wm.setGlobal( "list",
result );
+ // inserting fact
wm.insert( cheese );
+
+ // firing rules
wm.fireAllRules();
+
+ // checking results
assertEquals( 1,
result.size() );
- Integer r = (Integer) result.get( 0 );
assertEquals( new Integer( 5 ),
- r );
+ result.get( 0 ) );
+ // creating a person that likes the cheese:
+ // Retrieve the generated fact type
+ FactType personFact = ruleBase.getFactType( "org.drools.generatedbeans.Person" );
+
+ // Create a new Fact instance
+ Object person = personFact.newInstance();
+
+ // Set a field value using the more verbose method chain...
+ // should we add short cuts?
+ personFact.getField( "likes" ).getFieldAccessor().setValue( person,
+ cheese );
+ // demonstrating primitive type support
+ personFact.getField( "age" ).getFieldAccessor().setIntValue( person,
+ 7 );
+
+ // just documenting toString() result:
+ assertEquals( "Person( age=7, likes=Cheese( type=stilton ) )",
+ person.toString() );
+
+ // inserting fact
+ wm.insert( person );
+
+ // firing rules
+ wm.fireAllRules();
+
+ // checking results
+ assertEquals( 2,
+ result.size() );
+ assertEquals( "OK",
+ result.get( 1 ) );
+
}
public void testNullHandling() throws Exception {
@@ -971,7 +1002,7 @@
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final PersonInterface bill = new Person( "bill",
null,
@@ -1005,7 +1036,7 @@
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final PersonInterface bill = new Person( "bill",
null,
@@ -1167,7 +1198,7 @@
StatefulSession session = ruleBase.newStatefulSession();
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final Cheese cheddar = new Cheese( "cheddar",
5 );
@@ -1189,7 +1220,7 @@
list.size() );
session.insert( new Cheese( "stilton",
- 5 ) );
+ 5 ) );
session = SerializationHelper.getSerialisedStatefulSession( session,
ruleBase );
session.fireAllRules();
@@ -1230,11 +1261,11 @@
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "five",
- new Integer( 5 ) );
+ new Integer( 5 ) );
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final Cheese stilton = new Cheese( "stilton",
5 );
@@ -1262,11 +1293,11 @@
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "five",
- new Integer( 5 ) );
+ new Integer( 5 ) );
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final Cheese stilton = new Cheese( "stilton",
5 );
@@ -1291,7 +1322,7 @@
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final Person foo = new Person( "foo" );
session.insert( foo );
@@ -1314,11 +1345,11 @@
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "two",
- new Integer( 2 ) );
+ new Integer( 2 ) );
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final PersonInterface peter = new Person( "peter",
null,
@@ -1332,7 +1363,7 @@
session = SerializationHelper.getSerialisedStatefulSession( session,
ruleBase );
session.fireAllRules();
-
+
assertEquals( jane,
((List) session.getGlobal( "list" )).get( 0 ) );
assertEquals( peter,
@@ -1350,11 +1381,11 @@
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "two",
- new Integer( 2 ) );
+ new Integer( 2 ) );
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final PersonInterface peter = new Person( "peter",
null,
@@ -1367,7 +1398,7 @@
session = SerializationHelper.getSerialisedStatefulSession( session,
ruleBase );
- session.fireAllRules();
+ session.fireAllRules();
assertEquals( jane,
((List) session.getGlobal( "list" )).get( 0 ) );
@@ -1410,7 +1441,7 @@
StatefulSession session = ruleBase.newStatefulSession();
final List foo = new ArrayList();
session.setGlobal( "messages",
- foo );
+ foo );
final PersonInterface p1 = new Person( null,
"food",
@@ -1704,7 +1735,7 @@
final List list = new ArrayList();
session.setGlobal( "list",
- list );
+ list );
final Cheese stilton = new Cheese( "stilton",
5 );
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockRuleBase.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockRuleBase.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -14,6 +14,7 @@
import org.drools.TemporalSession;
import org.drools.event.RuleBaseEventListener;
import org.drools.marshalling.Marshaller;
+import org.drools.rule.FactType;
import org.drools.rule.Package;
public class MockRuleBase implements RuleBase {
@@ -166,4 +167,9 @@
// TODO Auto-generated method stub
}
+
+ public FactType getFactType(String string) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl 2008-05-20 01:53:38 UTC (rev 20072)
@@ -1,31 +1,27 @@
package org.drools.generatedbeans;
-
global java.util.List list;
-
declare Cheese
type: String
end
declare Person
- age: Integer
+ age: int
+ likes: Cheese
end
-
-
rule "simple rule"
when
- Cheese( )
+ Cheese( type == "stilton" )
then
list.add( new Integer(5) );
end
-
-
rule "another"
when
- Person( age== 7 )
+ $cheese : Cheese( type == "stilton" )
+ $person : Person( age== 7, likes == $cheese )
then
- list.add( new Integer(7) );
+ list.add( "OK" );
end
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -22,6 +22,7 @@
import java.io.OutputStream;
import org.drools.marshalling.Marshaller;
+import org.drools.rule.FactType;
import org.drools.rule.Package;
/**
@@ -190,4 +191,12 @@
* @return
*/
public StatefulSession[] getStatefulSessions();
+
+ /**
+ * Returns a declared FactType for external handling
+ *
+ * @param string
+ * @return
+ */
+ public FactType getFactType(String string);
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessor.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessor.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -22,8 +22,6 @@
import java.io.ObjectOutput;
import java.lang.reflect.Method;
-import org.drools.common.InternalWorkingMemory;
-
/**
* This is a wrapper for a ClassFieldExtractor that provides
* default values and a simpler interface for non-used parameters
@@ -161,127 +159,7 @@
}
/**
- * @param workingMemory
- * @param object
* @return
- * @see org.drools.base.ClassFieldReader#getBooleanValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public boolean getBooleanValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getBooleanValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getByteValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public byte getByteValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getByteValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getCharValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public char getCharValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getCharValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getDoubleValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public double getDoubleValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getDoubleValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getFloatValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public float getFloatValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getFloatValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getHashCode(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public int getHashCode(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getHashCode( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getIntValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public int getIntValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getIntValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getLongValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public long getLongValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getLongValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getShortValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public short getShortValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getShortValue( workingMemory,
- object );
- }
-
- /**
- * @param workingMemory
- * @param object
- * @return
- * @see org.drools.base.ClassFieldReader#getValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public Object getValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.getValue( workingMemory,
- object );
- }
-
- /**
- * @return
* @see org.drools.base.ClassFieldReader#isGlobal()
*/
public boolean isGlobal() {
@@ -289,19 +167,7 @@
}
/**
- * @param workingMemory
- * @param object
* @return
- * @see org.drools.base.ClassFieldReader#isNullValue(org.drools.common.InternalWorkingMemory, java.lang.Object)
- */
- public boolean isNullValue(InternalWorkingMemory workingMemory,
- Object object) {
- return reader.isNullValue( workingMemory,
- object );
- }
-
- /**
- * @return
* @see org.drools.base.ClassFieldWriter#getFieldType()
*/
public Class< ? > getFieldType() {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -54,6 +54,7 @@
import org.drools.reteoo.ReteooStatefulSession;
import org.drools.rule.CompositePackageClassLoader;
import org.drools.rule.DialectDatas;
+import org.drools.rule.FactType;
import org.drools.rule.Function;
import org.drools.rule.ImportDeclaration;
import org.drools.rule.InvalidPatternException;
@@ -854,6 +855,16 @@
}
return false;
}
+
+ public FactType getFactType( final String name ) {
+ for ( Package pkg : this.pkgs.values() ) {
+ FactType type = pkg.getFactType( name );
+ if( type != null ) {
+ return type;
+ }
+ }
+ return null;
+ }
public static class ReloadPackageCompilationData
implements
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -33,13 +33,33 @@
* @author etirelli
*/
public class ClassBuilder {
- private boolean debug = false;
+ private boolean debug = false;
+ private ClassLoader loader = null;
public ClassBuilder() {
- this( "true".equalsIgnoreCase( System.getProperty( "org.drools.classbuilder.debug" ) ) );
+ this( null,
+ "true".equalsIgnoreCase( System.getProperty( "org.drools.classbuilder.debug" ) ) );
}
public ClassBuilder(final boolean debug) {
+ this( null,
+ debug );
+ }
+
+ public ClassBuilder(final ClassLoader loader) {
+ this( loader,
+ false );
+ }
+
+ public ClassBuilder(final ClassLoader loader,
+ final boolean debug) {
+ this.loader = loader;
+ if ( this.loader == null ) {
+ this.loader = Thread.currentThread().getContextClassLoader();
+ if ( this.loader == null ) {
+ this.loader = getClass().getClassLoader();
+ }
+ }
this.debug = debug;
}
@@ -125,7 +145,7 @@
classDef );
// Building fields
- for ( FieldDefinition fieldDef : classDef.getFields() ) {
+ for ( FieldDefinition fieldDef : classDef.getFieldsDefinitions() ) {
this.buildField( cw,
fieldDef );
}
@@ -135,7 +155,7 @@
classDef );
// Building methods
- for ( FieldDefinition fieldDef : classDef.getFields() ) {
+ for ( FieldDefinition fieldDef : classDef.getFieldsDefinitions() ) {
this.buildGetMethod( cw,
classDef,
fieldDef );
@@ -165,13 +185,18 @@
*/
private void buildClassHeader(ClassWriter cw,
ClassDefinition classDef) {
+ String[] original = classDef.getInterfaces();
+ String[] interfaces = new String[ original.length ];
+ for( int i = 0; i < original.length; i++ ) {
+ interfaces[i] = getInternalType( original[i] );
+ }
// Building class header
cw.visit( Opcodes.V1_4,
Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
null,
- classDef.getSuperClassAsInternal(),
- classDef.getInterfacesAsInternal() );
+ getInternalType( classDef.getSuperClass() ),
+ interfaces );
cw.visitSource( classDef.getClassName() + ".java",
null );
@@ -188,7 +213,7 @@
FieldVisitor fv;
fv = cw.visitField( Opcodes.ACC_PRIVATE,
fieldDef.getName(),
- fieldDef.getInternalType(),
+ getTypeDescriptor( fieldDef.getTypeName() ),
null,
null );
fv.visitEnd();
@@ -229,7 +254,7 @@
l1 = new Label();
mv.visitLabel( l1 );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
l1,
@@ -257,7 +282,7 @@
mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
fieldDef.getWriteMethod(),
Type.getMethodDescriptor( Type.VOID_TYPE,
- new Type[]{Type.getType( fieldDef.getInternalType() )} ),
+ new Type[]{Type.getType( getTypeDescriptor( fieldDef.getTypeName() ) )} ),
null,
null );
mv.visitCode();
@@ -268,12 +293,12 @@
}
mv.visitVarInsn( Opcodes.ALOAD,
0 );
- mv.visitVarInsn( Type.getType( fieldDef.getInternalType() ).getOpcode( Opcodes.ILOAD ),
+ mv.visitVarInsn( Type.getType( getTypeDescriptor( fieldDef.getTypeName() ) ).getOpcode( Opcodes.ILOAD ),
1 );
mv.visitFieldInsn( Opcodes.PUTFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
fieldDef.getName(),
- fieldDef.getInternalType() );
+ getTypeDescriptor( fieldDef.getTypeName() ) );
mv.visitInsn( Opcodes.RETURN );
Label l1 = null;
@@ -281,7 +306,7 @@
l1 = new Label();
mv.visitLabel( l1 );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
l1,
@@ -308,7 +333,7 @@
{
mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
fieldDef.getReadMethod(),
- Type.getMethodDescriptor( Type.getType( fieldDef.getInternalType() ),
+ Type.getMethodDescriptor( Type.getType( getTypeDescriptor( fieldDef.getTypeName() ) ),
new Type[]{} ),
null,
null );
@@ -321,16 +346,16 @@
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
fieldDef.getName(),
- fieldDef.getInternalType() );
- mv.visitInsn( Type.getType( fieldDef.getInternalType() ).getOpcode( Opcodes.IRETURN ) );
+ getTypeDescriptor( fieldDef.getTypeName() ) );
+ mv.visitInsn( Type.getType( getTypeDescriptor( fieldDef.getTypeName() ) ).getOpcode( Opcodes.IRETURN ) );
Label l1 = null;
if ( this.debug ) {
l1 = new Label();
mv.visitLabel( l1 );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
l1,
@@ -358,6 +383,8 @@
l0 = new Label();
mv.visitLabel( l0 );
}
+
+ // if ( this == obj ) return true;
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitVarInsn( Opcodes.ALOAD,
@@ -367,112 +394,148 @@
l1 );
mv.visitInsn( Opcodes.ICONST_1 );
mv.visitInsn( Opcodes.IRETURN );
+
+ // if ( obj == null ) return false;
mv.visitLabel( l1 );
mv.visitVarInsn( Opcodes.ALOAD,
1 );
+ Label l2 = new Label();
+ mv.visitJumpInsn( Opcodes.IFNONNULL,
+ l2 );
+ mv.visitInsn( Opcodes.ICONST_0 );
+ mv.visitInsn( Opcodes.IRETURN );
+
+ // if ( getClass() != obj.getClass() ) return false;
+ mv.visitLabel( l2 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( Object.class ),
+ "getClass",
+ Type.getMethodDescriptor( Type.getType( Class.class ),
+ new Type[]{} ) );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( Object.class ),
+ "getClass",
+ Type.getMethodDescriptor( Type.getType( Class.class ),
+ new Type[]{} ) );
Label l3 = new Label();
- mv.visitJumpInsn( Opcodes.IFNULL,
+ mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
l3 );
- mv.visitVarInsn( Opcodes.ALOAD,
- 1 );
- mv.visitTypeInsn( Opcodes.INSTANCEOF,
- classDef.getClassNameAsInternal() );
- Label l4 = new Label();
- mv.visitJumpInsn( Opcodes.IFNE,
- l4 );
- mv.visitLabel( l3 );
mv.visitInsn( Opcodes.ICONST_0 );
mv.visitInsn( Opcodes.IRETURN );
- mv.visitLabel( l4 );
+
+ // final <classname> other = (<classname>) obj;
+ mv.visitLabel( l3 );
mv.visitVarInsn( Opcodes.ALOAD,
1 );
mv.visitTypeInsn( Opcodes.CHECKCAST,
- classDef.getClassNameAsInternal() );
+ getInternalType( classDef.getClassName() ) );
mv.visitVarInsn( Opcodes.ASTORE,
2 );
+ // for each key field
int count = 0;
- for ( FieldDefinition field : classDef.getFields() ) {
+ for ( FieldDefinition field : classDef.getFieldsDefinitions() ) {
if ( field.isKey() ) {
count++;
+
Label goNext = new Label();
- if ( field.isPrimitive() ) {
+
+ if ( isPrimitive( field.getTypeName() ) ) {
+ // if attr is primitive
+
+ // if ( this.<attr> != other.<booleanAttr> ) return false;
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
+
mv.visitVarInsn( Opcodes.ALOAD,
2 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
- if ( field.getType().equals( "long" ) ) {
+ getTypeDescriptor( field.getTypeName() ) );
+
+ if ( field.getTypeName().equals( "long" ) ) {
mv.visitInsn( Opcodes.LCMP );
mv.visitJumpInsn( Opcodes.IFEQ,
goNext );
- } else if ( field.getType().equals( "double" ) ) {
+ } else if ( field.getTypeName().equals( "double" ) ) {
mv.visitInsn( Opcodes.DCMPL );
mv.visitJumpInsn( Opcodes.IFEQ,
goNext );
- } else if ( field.getType().equals( "float" ) ) {
+ } else if ( field.getTypeName().equals( "float" ) ) {
mv.visitInsn( Opcodes.FCMPL );
mv.visitJumpInsn( Opcodes.IFEQ,
goNext );
} else {
+ // boolean, byte, char, short, int
mv.visitJumpInsn( Opcodes.IF_ICMPEQ,
goNext );
}
mv.visitInsn( Opcodes.ICONST_0 );
mv.visitInsn( Opcodes.IRETURN );
} else {
+ // if attr is not a primitive
+
+ // if ( this.<attr> == null && other.<attr> != null ||
+ // this.<attr> != null && ! this.<attr>.equals( other.<attr> ) ) return false;
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
Label secondIfPart = new Label();
mv.visitJumpInsn( Opcodes.IFNONNULL,
secondIfPart );
+
+ // if ( other.objAttr != null ) return false;
mv.visitVarInsn( Opcodes.ALOAD,
2 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
Label returnFalse = new Label();
mv.visitJumpInsn( Opcodes.IFNONNULL,
returnFalse );
+
mv.visitLabel( secondIfPart );
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
mv.visitJumpInsn( Opcodes.IFNULL,
goNext );
+
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
mv.visitVarInsn( Opcodes.ALOAD,
2 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- field.getBoxTypeName(),
+ getInternalType( field.getTypeName() ),
"equals",
"(Ljava/lang/Object;)Z" );
mv.visitJumpInsn( Opcodes.IFNE,
goNext );
+
mv.visitLabel( returnFalse );
mv.visitInsn( Opcodes.ICONST_0 );
mv.visitInsn( Opcodes.IRETURN );
@@ -491,7 +554,7 @@
lastLabel = new Label();
mv.visitLabel( lastLabel );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
lastLabel,
@@ -503,7 +566,7 @@
lastLabel,
1 );
mv.visitLocalVariable( "other",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
lastLabel,
@@ -532,42 +595,101 @@
l0 = new Label();
mv.visitLabel( l0 );
}
- mv.visitInsn( Opcodes.ICONST_0 );
+
+ // int result = 1;
+ mv.visitInsn( Opcodes.ICONST_1 );
mv.visitVarInsn( Opcodes.ISTORE,
1 );
- for ( FieldDefinition field : classDef.getFields() ) {
+ // for each key field
+ for ( FieldDefinition field : classDef.getFieldsDefinitions() ) {
if ( field.isKey() ) {
+
+ // result = result * 31 + <attr_hash>
mv.visitVarInsn( Opcodes.ILOAD,
1 );
- if ( field.isPrimitive() ) {
- mv.visitTypeInsn( Opcodes.NEW,
- field.getBoxTypeName() );
- mv.visitInsn( Opcodes.DUP );
+ mv.visitIntInsn( Opcodes.BIPUSH,
+ 31 );
+ mv.visitVarInsn( Opcodes.ILOAD,
+ 1 );
+ mv.visitInsn( Opcodes.IMUL );
+
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ getInternalType( classDef.getClassName() ),
+ field.getName(),
+ getTypeDescriptor( field.getTypeName() ) );
+
+ if ( "boolean".equals( field.getTypeName() ) ) {
+ // attr_hash ::== <boolean_attr> ? 1231 : 1237;
+ Label blabel1 = new Label();
+ mv.visitJumpInsn( Opcodes.IFEQ,
+ blabel1 );
+ mv.visitIntInsn( Opcodes.SIPUSH,
+ 1231 );
+ Label blabel2 = new Label();
+ mv.visitJumpInsn( Opcodes.GOTO,
+ blabel2 );
+ mv.visitLabel( blabel1 );
+ mv.visitIntInsn( Opcodes.SIPUSH,
+ 1237 );
+ mv.visitLabel( blabel2 );
+ } else if ( "long".equals( field.getTypeName() ) ) {
+ // attr_hash ::== (int) (longAttr ^ (longAttr >>> 32))
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
- mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
- field.getBoxTypeName(),
- "<init>",
- Type.getMethodDescriptor( Type.VOID_TYPE,
- new Type[]{Type.getType( field.getInternalType() )} ) );
- } else {
+ getTypeDescriptor( field.getTypeName() ) );
+ mv.visitIntInsn( Opcodes.BIPUSH,
+ 32 );
+ mv.visitInsn( Opcodes.LUSHR );
+ mv.visitInsn( Opcodes.LXOR );
+ mv.visitInsn( Opcodes.L2I );
+
+ } else if ( "float".equals( field.getTypeName() ) ) {
+ // attr_hash ::== Float.floatToIntBits( floatAttr );
+ mv.visitMethodInsn( Opcodes.INVOKESTATIC,
+ Type.getInternalName( Float.class ),
+ "floatToIntBits",
+ "(F)I" );
+ } else if ( "double".equals( field.getTypeName() ) ) {
+ // attr_hash ::== (int) (Double.doubleToLongBits( doubleAttr ) ^ (Double.doubleToLongBits( doubleAttr ) >>> 32));
+ mv.visitMethodInsn( Opcodes.INVOKESTATIC,
+ Type.getInternalName( Double.class ),
+ "doubleToLongBits",
+ "(D)J" );
+ mv.visitInsn( Opcodes.DUP2 );
+ mv.visitIntInsn( Opcodes.BIPUSH,
+ 32 );
+ mv.visitInsn( Opcodes.LUSHR );
+ mv.visitInsn( Opcodes.LXOR );
+ mv.visitInsn( Opcodes.L2I );
+ } else if ( !isPrimitive( field.getTypeName() ) ) {
+ // attr_hash ::== ((objAttr == null) ? 0 : objAttr.hashCode());
+ Label olabel1 = new Label();
+ mv.visitJumpInsn( Opcodes.IFNONNULL,
+ olabel1 );
+ mv.visitInsn( Opcodes.ICONST_0 );
+ Label olabel2 = new Label();
+ mv.visitJumpInsn( Opcodes.GOTO,
+ olabel2 );
+ mv.visitLabel( olabel1 );
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ getInternalType( field.getTypeName() ),
+ "hashCode",
+ "()I" );
+ mv.visitLabel( olabel2 );
+ }
- }
- mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- field.getBoxTypeName(),
- "hashCode",
- "()I" );
mv.visitInsn( Opcodes.IADD );
mv.visitVarInsn( Opcodes.ISTORE,
1 );
@@ -575,9 +697,6 @@
}
mv.visitVarInsn( Opcodes.ILOAD,
1 );
- mv.visitIntInsn( Opcodes.SIPUSH,
- 9653 );
- mv.visitInsn( Opcodes.IREM );
mv.visitInsn( Opcodes.IRETURN );
Label lastLabel = null;
@@ -585,7 +704,7 @@
lastLabel = new Label();
mv.visitLabel( lastLabel );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
lastLabel,
@@ -622,10 +741,10 @@
// StringBuffer buf = new StringBuffer();
mv.visitTypeInsn( Opcodes.NEW,
- "java/lang/StringBuffer" );
+ Type.getInternalName( StringBuffer.class ) );
mv.visitInsn( Opcodes.DUP );
mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"<init>",
"()V" );
mv.visitVarInsn( Opcodes.ASTORE,
@@ -637,46 +756,46 @@
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
"getClass",
"()Ljava/lang/Class;" );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/Class",
+ Type.getInternalName( Class.class ),
"getSimpleName",
"()Ljava/lang/String;" );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
// buf.append("( ");
mv.visitLdcInsn( "( " );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
boolean previous = false;
- for ( FieldDefinition field : classDef.getFields() ) {
+ for ( FieldDefinition field : classDef.getFieldsDefinitions() ) {
if ( previous ) {
// buf.append(", ");
mv.visitLdcInsn( ", " );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
}
// buf.append(attrName)
mv.visitLdcInsn( field.getName() );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
// buf.append("=");
mv.visitLdcInsn( "=" );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
@@ -684,19 +803,19 @@
mv.visitVarInsn( Opcodes.ALOAD,
0 );
mv.visitFieldInsn( Opcodes.GETFIELD,
- classDef.getClassNameAsInternal(),
+ getInternalType( classDef.getClassName() ),
field.getName(),
- field.getInternalType() );
+ getTypeDescriptor( field.getTypeName() ) );
- if ( field.isPrimitive() ) {
+ if ( isPrimitive( field.getTypeName() ) ) {
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
Type.getMethodDescriptor( Type.getType( StringBuffer.class ),
- new Type[]{Type.getType( field.getInternalType() )} ) );
+ new Type[]{Type.getType( getTypeDescriptor( field.getTypeName() ) )} ) );
} else {
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
Type.getMethodDescriptor( Type.getType( StringBuffer.class ),
new Type[]{Type.getType( Object.class )} ) );
@@ -706,11 +825,11 @@
mv.visitLdcInsn( " )" );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
- "java/lang/StringBuffer",
+ Type.getInternalName( StringBuffer.class ),
"toString",
"()Ljava/lang/String;" );
mv.visitInsn( Opcodes.ARETURN );
@@ -720,7 +839,7 @@
lastLabel = new Label();
mv.visitLabel( lastLabel );
mv.visitLocalVariable( "this",
- classDef.getInternalName(),
+ getTypeDescriptor( classDef.getClassName() ),
null,
l0,
lastLabel,
@@ -764,4 +883,98 @@
return clazz;
}
+ /**
+ * Returns the corresponding internal type representation for the
+ * given type.
+ *
+ * I decided to not use the ASM Type class methods because they require
+ * resolving the actual type into a Class instance and at this point,
+ * I think it is best to delay type resolution until it is really needed.
+ *
+ * @param type
+ * @return
+ */
+ private String getInternalType(String type) {
+ String internalType = null;
+ if ( "byte".equals( type ) ) {
+ internalType = "B";
+ } else if ( "char".equals( type ) ) {
+ internalType = "C";
+ } else if ( "double".equals( type ) ) {
+ internalType = "D";
+ } else if ( "float".equals( type ) ) {
+ internalType = "F";
+ } else if ( "int".equals( type ) ) {
+ internalType = "I";
+ } else if ( "long".equals( type ) ) {
+ internalType = "J";
+ } else if ( "short".equals( type ) ) {
+ internalType = "S";
+ } else if ( "boolean".equals( type ) ) {
+ internalType = "Z";
+ } else if ( "void".equals( type ) ) {
+ internalType = "V";
+ } else if ( type != null ) {
+ // I think this will fail for inner classes, but we don't really
+ // support inner class generation at the moment
+ internalType = type.replace( '.',
+ '/' );
+ }
+ return internalType;
+ }
+
+ /**
+ * Returns the corresponding type descriptor for the
+ * given type.
+ *
+ * I decided to not use the ASM Type class methods because they require
+ * resolving the actual type into a Class instance and at this point,
+ * I think it is best to delay type resolution until it is really needed.
+ *
+ * @param type
+ * @return
+ */
+ private String getTypeDescriptor(String type) {
+ String internalType = null;
+ if ( "byte".equals( type ) ) {
+ internalType = "B";
+ } else if ( "char".equals( type ) ) {
+ internalType = "C";
+ } else if ( "double".equals( type ) ) {
+ internalType = "D";
+ } else if ( "float".equals( type ) ) {
+ internalType = "F";
+ } else if ( "int".equals( type ) ) {
+ internalType = "I";
+ } else if ( "long".equals( type ) ) {
+ internalType = "J";
+ } else if ( "short".equals( type ) ) {
+ internalType = "S";
+ } else if ( "boolean".equals( type ) ) {
+ internalType = "Z";
+ } else if ( "void".equals( type ) ) {
+ internalType = "V";
+ } else if ( type != null ) {
+ // I think this will fail for inner classes, but we don't really
+ // support inner class generation at the moment
+ internalType = "L" + type.replace( '.',
+ '/' ) + ";";
+ }
+ return internalType;
+ }
+
+ /**
+ * Returns true if the provided type is a primitive type
+ *
+ * @param type
+ * @return
+ */
+ private boolean isPrimitive(String type) {
+ boolean isPrimitive = false;
+ if ( "byte".equals( type ) || "char".equals( type ) || "double".equals( type ) || "float".equals( type ) || "int".equals( type ) || "long".equals( type ) || "short".equals( type ) || "boolean".equals( type ) || "void".equals( type ) ) {
+ isPrimitive = true;
+ }
+ return isPrimitive;
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -19,22 +19,26 @@
import java.beans.IntrospectionException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import org.drools.base.ClassFieldAccessor;
import org.drools.base.ClassFieldAccessorCache;
import org.drools.base.ClassFieldReader;
import org.drools.base.ClassFieldWriter;
+import org.drools.rule.FactField;
+import org.drools.rule.FactType;
/**
* Declares a class to be dynamically created
*
* @author etirelli
*/
-public class ClassDefinition {
+public class ClassDefinition implements FactType {
private String className;
private String superClass;
private String[] interfaces;
@@ -85,21 +89,6 @@
}
/**
- * @return the class name replacing '.' by '/'
- */
- final String getClassNameAsInternal() {
- return this.getClassName().replace( '.',
- '/' );
- }
-
- /**
- * @return Returns the name.
- */
- public final String getInternalName() {
- return "L" + this.getClassNameAsInternal() + ";";
- }
-
- /**
* @return Returns the className.
*/
public final Class< ? > getDefinedClass() {
@@ -107,34 +96,11 @@
}
/**
- * @param className The className to set.
- * @throws IntrospectionException
- * @throws NoSuchFieldException
- * @throws InvocationTargetException
- * @throws NoSuchMethodException
- * @throws ClassNotFoundException
- * @throws IOException
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws IllegalArgumentException
- * @throws SecurityException
+ * @param className The class to set.
*/
- final void setDefinedClass(final Class< ? > definedClass) throws IntrospectionException,
- SecurityException,
- IllegalArgumentException,
- InstantiationException,
- IllegalAccessException,
- IOException,
- ClassNotFoundException,
- NoSuchMethodException,
- InvocationTargetException,
- NoSuchFieldException {
+ public void setDefinedClass(final Class< ? > definedClass) {
this.definedClass = definedClass;
-
- if ( this.definedClass != null ) {
- this.buildFieldAccessors();
- }
}
/**
@@ -149,7 +115,7 @@
/**
* @return Returns an unmodifiable collection of field definitions
*/
- public final Collection<FieldDefinition> getFields() {
+ public final Collection<FieldDefinition> getFieldsDefinitions() {
return Collections.unmodifiableCollection( this.fields.values() );
}
@@ -212,18 +178,6 @@
}
/**
- * @return
- */
- final String[] getInterfacesAsInternal() {
- String[] interfaces = new String[this.interfaces.length];
- for ( int i = 0; i < interfaces.length; i++ ) {
- interfaces[i] = this.interfaces[i].replace( '.',
- '/' );
- }
- return interfaces;
- }
-
- /**
* @return Returns the superClass.
*/
public final String getSuperClass() {
@@ -234,15 +188,23 @@
* @param superClass The superClass to set.
*/
public final void setSuperClass(final String superClass) {
- this.superClass = (superClass != null) ? superClass : "java/lang/Object";
+ this.superClass = (superClass != null) ? superClass : "java.lang.Object";
}
- /**
- * @return Returns superclass name in the internal String representation
- */
- final String getSuperClassAsInternal() {
- return this.superClass.replace( '.',
- '/' );
+ public String getName() {
+ return getClassName();
}
+ public Object newInstance() throws InstantiationException, IllegalAccessException {
+ return this.definedClass.newInstance();
+ }
+
+ public Class< ? > getFactClass() {
+ return getDefinedClass();
+ }
+
+ public List<FactField> getFields() {
+ return new ArrayList<FactField>( fields.values() );
+ }
+
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -19,21 +19,18 @@
import java.lang.reflect.InvocationTargetException;
import org.drools.base.ClassFieldAccessor;
+import org.drools.rule.FactField;
/**
* Declares a field to be dynamically generated.
*
* @author etirelli
*/
-public class FieldDefinition {
+public class FieldDefinition implements FactField {
private String name = null;
private String type = null;
private boolean key = false;
- private String internalType = null;
- private String boxTypeName = null;
- private boolean primitive = false;
- private String unboxMethod = null;
private ClassFieldAccessor accessor = null;
/**
@@ -61,7 +58,6 @@
this.name = name;
this.type = type;
this.key = key;
- this.setInternals();
}
/**
@@ -81,44 +77,22 @@
/**
* @return Returns the fully qualified type.
*/
- public String getType() {
+ public String getTypeName() {
return this.type;
}
/**
* @param type The fully qualified type to set.
*/
- public void setType(String type) {
+ public void setTypeName(String type) {
this.type = type;
- this.setInternals();
}
- /**
- * @return Returns the fully qualified internal type representation
- */
- String getInternalType() {
- return this.internalType;
+ public Class< ? > getType() {
+ return this.accessor.getFieldType();
}
- String getBoxTypeName() {
- return this.boxTypeName;
- }
-
/**
- * @return Returns the primitive.
- */
- boolean isPrimitive() {
- return primitive;
- }
-
- /**
- * @return Returns the unboxMethod.
- */
- String getUnboxMethod() {
- return unboxMethod;
- }
-
- /**
* @return Returns the key.
*/
public boolean isKey() {
@@ -225,66 +199,4 @@
return this.accessor.getValue( bean );
}
- /**
- * Creates the internal string representation of this attribute's type
- *
- * @param type
- * @return
- */
- private void setInternals() {
- if ( "byte".equals( this.type ) ) {
- this.internalType = "B";
- this.boxTypeName = "java/lang/Byte";
- this.primitive = true;
- this.unboxMethod = "byteValue";
- } else if ( "char".equals( type ) ) {
- this.internalType = "C";
- this.boxTypeName = "java/lang/Character";
- this.primitive = true;
- this.unboxMethod = "charValue";
- } else if ( "double".equals( type ) ) {
- this.internalType = "D";
- this.boxTypeName = "java/lang/Double";
- this.primitive = true;
- this.unboxMethod = "doubleValue";
- } else if ( "float".equals( type ) ) {
- this.internalType = "F";
- this.boxTypeName = "java/lang/Float";
- this.primitive = true;
- this.unboxMethod = "floatValue";
- } else if ( "int".equals( type ) ) {
- this.internalType = "I";
- this.boxTypeName = "java/lang/Integer";
- this.primitive = true;
- this.unboxMethod = "intValue";
- } else if ( "long".equals( type ) ) {
- this.internalType = "J";
- this.boxTypeName = "java/lang/Long";
- this.primitive = true;
- this.unboxMethod = "longValue";
- } else if ( "short".equals( type ) ) {
- this.internalType = "S";
- this.boxTypeName = "java/lang/Short";
- this.primitive = true;
- this.unboxMethod = "shortValue";
- } else if ( "boolean".equals( type ) ) {
- this.internalType = "Z";
- this.boxTypeName = "java/lang/Boolean";
- this.primitive = true;
- this.unboxMethod = "booleanValue";
- } else if ( "void".equals( type ) ) {
- this.internalType = "V";
- this.boxTypeName = "java/lang/Void";
- this.primitive = true;
- this.unboxMethod = null;
- } else if ( type != null ) {
- this.internalType = "L" + type.replace( '.',
- '/' ) + ";";
- this.boxTypeName = type.replace( '.',
- '/' );
- this.primitive = false;
- this.unboxMethod = null;
- }
- }
-
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/DialectDatas.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/DialectDatas.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/DialectDatas.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -1,7 +1,5 @@
package org.drools.rule;
-import org.drools.common.DroolsObjectInput;
-
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 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.
+ *
+ * Created on May 19, 2008
+ */
+
+package org.drools.rule;
+
+import org.drools.base.FieldAccessor;
+
+/**
+ * An interface for Fact Fields
+ *
+ * @author etirelli
+ */
+public interface FactField {
+
+ public Class<?> getType();
+
+ public String getName();
+
+ public boolean isKey();
+
+ public FieldAccessor getFieldAccessor();
+
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 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.
+ *
+ * Created on May 19, 2008
+ */
+
+package org.drools.rule;
+
+import java.util.List;
+
+/**
+ * An interface for FactType declarations
+ *
+ * @author etirelli
+ */
+public interface FactType {
+
+ public String getName();
+
+ public List<FactField> getFields();
+
+ public FactField getField( String name );
+
+ public Class<?> getFactClass();
+
+ public Object newInstance() throws InstantiationException, IllegalAccessException;
+}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -29,7 +29,6 @@
import java.util.Map;
import java.util.Set;
-import org.drools.common.DroolsObjectInput;
import org.drools.common.DroolsObjectInputStream;
import org.drools.common.DroolsObjectOutputStream;
import org.drools.facttemplates.FactTemplate;
@@ -88,7 +87,7 @@
/** This will keep a summary error message as to why this package is not valid */
private String errorSummary;
-
+
// ------------------------------------------------------------
// Constructors
// ------------------------------------------------------------
@@ -524,4 +523,14 @@
this.factTemplates.clear();
this.typeDeclarations.clear();
}
+
+ public FactType getFactType(final String typeName) {
+ if( this.name != null && ! typeName.startsWith( this.name ) ) {
+ return null;
+ }
+ // in case the package name is != null, remove the package name from the beginning of the type name
+ String key = this.name == null ? typeName : typeName.substring( this.name.length()+1 );
+ TypeDeclaration decl = this.typeDeclarations.get( key );
+ return decl != null ? decl.getTypeClassDef() : null;
+ }
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/TypeDeclaration.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/TypeDeclaration.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/TypeDeclaration.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -24,6 +24,7 @@
import java.io.ObjectOutput;
import org.drools.common.DroolsObjectInputStream;
+import org.drools.factmodel.ClassDefinition;
import org.drools.facttemplates.FactTemplate;
import org.drools.spi.InternalReadAccessor;
@@ -80,6 +81,7 @@
private transient InternalReadAccessor durationExtractor;
private Class< ? > typeClass;
private FactTemplate typeTemplate;
+ private ClassDefinition typeClassDef;
public TypeDeclaration() {
}
@@ -103,6 +105,7 @@
this.timestampAttribute = (String) in.readObject();
this.typeClass = (Class< ? >) in.readObject();
this.typeTemplate = (FactTemplate) in.readObject();
+ this.typeClassDef = (ClassDefinition) in.readObject();
if ( this.durationAttribute != null ) {
// generate the extractor
@@ -121,6 +124,7 @@
out.writeObject( timestampAttribute );
out.writeObject( typeClass );
out.writeObject( typeTemplate );
+ out.writeObject( typeClassDef );
}
/**
@@ -198,6 +202,9 @@
*/
public void setTypeClass(Class< ? > typeClass) {
this.typeClass = typeClass;
+ if( this.typeClassDef != null ) {
+ this.typeClassDef.setDefinedClass( this.typeClass );
+ }
}
/**
@@ -258,4 +265,18 @@
this.durationExtractor = durationExtractor;
}
+ /**
+ * @return the typeClassDef
+ */
+ public ClassDefinition getTypeClassDef() {
+ return typeClassDef;
+ }
+
+ /**
+ * @param typeClassDef the typeClassDef to set
+ */
+ public void setTypeClassDef(ClassDefinition typeClassDef) {
+ this.typeClassDef = typeClassDef;
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java 2008-05-20 00:14:17 UTC (rev 20071)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java 2008-05-20 01:53:38 UTC (rev 20072)
@@ -12,13 +12,20 @@
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
+import org.drools.base.ClassFieldAccessorCache;
+
import junit.framework.Assert;
import junit.framework.TestCase;
public class ClassBuilderTest extends TestCase {
+ private ClassFieldAccessorCache cache;
+ private ClassLoader classLoader;
+
protected void setUp() throws Exception {
super.setUp();
+ cache = ClassFieldAccessorCache.getInstance();
+ classLoader = this.getClass().getClassLoader();
}
protected void tearDown() throws Exception {
@@ -45,6 +52,8 @@
classDef.addField( stringDef );
Class clazz = builder.buildAndLoadClass( classDef );
+ intDef.setFieldAccessor( cache.getAccessor( clazz, intDef.getName(), classLoader ) );
+ stringDef.setFieldAccessor( cache.getAccessor( clazz, stringDef.getName(), classLoader ) );
byte[] data = builder.buildClass(classDef);
@@ -136,6 +145,15 @@
classDef.addField( str2Def );
Class clazz = builder.buildAndLoadClass( classDef );
+ long1Def.setFieldAccessor( cache.getAccessor( clazz, long1Def.getName(), classLoader ) );
+ long2Def.setFieldAccessor( cache.getAccessor( clazz, long2Def.getName(), classLoader ) );
+ doubleDef.setFieldAccessor( cache.getAccessor( clazz, doubleDef.getName(), classLoader ) );
+ intDef.setFieldAccessor( cache.getAccessor( clazz, intDef.getName(), classLoader ) );
+ strDef.setFieldAccessor( cache.getAccessor( clazz, strDef.getName(), classLoader ) );
+ dateDef.setFieldAccessor( cache.getAccessor( clazz, dateDef.getName(), classLoader ) );
+ str2Def.setFieldAccessor( cache.getAccessor( clazz, str2Def.getName(), classLoader ) );
+
+
Object x = clazz.newInstance();
Object y = clazz.newInstance();
@@ -224,13 +242,16 @@
classDef.addField( strDef );
Class clazz = builder.buildAndLoadClass( classDef );
+ intDef.setFieldAccessor( cache.getAccessor( clazz, intDef.getName(), classLoader ) );
+ strDef.setFieldAccessor( cache.getAccessor( clazz, strDef.getName(), classLoader ) );
+
Object x = clazz.newInstance();
intDef.setValue( x,
new Integer( 10 ) );
strDef.setValue( x, "abc" );
- Assert.assertEquals("Wrong hashcode calculation", (new Integer(10)).hashCode(), x.hashCode());
+ Assert.assertEquals("Wrong hashcode calculation", 31+10, x.hashCode());
Assert.assertEquals("Wrong hashcode calculation", x.hashCode(), x.hashCode());
} catch ( Exception e ) {
@@ -275,6 +296,14 @@
classDef.addField( str2Def );
Class clazz = builder.buildAndLoadClass( classDef );
+ long1Def.setFieldAccessor( cache.getAccessor( clazz, long1Def.getName(), classLoader ) );
+ long2Def.setFieldAccessor( cache.getAccessor( clazz, long2Def.getName(), classLoader ) );
+ doubleDef.setFieldAccessor( cache.getAccessor( clazz, doubleDef.getName(), classLoader ) );
+ intDef.setFieldAccessor( cache.getAccessor( clazz, intDef.getName(), classLoader ) );
+ strDef.setFieldAccessor( cache.getAccessor( clazz, strDef.getName(), classLoader ) );
+ dateDef.setFieldAccessor( cache.getAccessor( clazz, dateDef.getName(), classLoader ) );
+ str2Def.setFieldAccessor( cache.getAccessor( clazz, str2Def.getName(), classLoader ) );
+
Object x = clazz.newInstance();
long1Def.setValue( x,
More information about the jboss-svn-commits
mailing list