[jboss-svn-commits] JBL Code SVN: r28125 - in labs/jbossrules/trunk: drools-compiler/src/main/java/org/drools/reteoo and 4 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Jul 16 21:22:31 EDT 2009
Author: stampy88
Date: 2009-07-16 21:22:31 -0400 (Thu, 16 Jul 2009)
New Revision: 28125
Added:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/compiled/
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeCompiler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AbstractCompilerHandler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AssertHandler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/CompiledNetwork.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/DeclarationsHandler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/HashedAlphasDeclaration.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandlerAdaptor.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeParser.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/SetNodeReferenceHandler.java
Removed:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNetworkCompiler.java
Modified:
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/manners/MannersBenchmark.java
Log:
Initial version of compiled network
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeCompiler.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeCompiler.java (rev 0)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeCompiler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,185 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.compiler.PackageBuilder;
+import org.drools.compiler.PackageRegistry;
+import org.drools.lang.descr.PackageDescr;
+import org.drools.reteoo.ObjectTypeNode;
+import org.drools.rule.builder.dialect.java.JavaDialect;
+
+import java.util.Collection;
+
+/**
+ * todo: document
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+public class ObjectTypeNodeCompiler {
+ private static final String NEWLINE = "\n";
+ private static final String PACKAGE_NAME = "org.drools.reteoo.compiled";
+ private static final String BINARY_PACKAGE_NAME = PACKAGE_NAME.replaceAll("\\.", "/");
+ /**
+ * This field hold the fully qualified class name that the {@link org.drools.reteoo.ObjectTypeNode} is representing.
+ */
+ private String className;
+
+ /**
+ * This field will hold the "simple" name of the generated class
+ */
+ private String generatedClassSimpleName;
+
+ /**
+ * OTN we are creating a compiled network for
+ */
+ private ObjectTypeNode objectTypeNode;
+
+ private StringBuilder builder = new StringBuilder();
+
+ private ObjectTypeNodeCompiler(ObjectTypeNode objectTypeNode) {
+ this.objectTypeNode = objectTypeNode;
+
+ ClassObjectType classObjectType = (ClassObjectType) objectTypeNode.getObjectType();
+ this.className = classObjectType.getClassName();
+ generatedClassSimpleName = "Compiled" + classObjectType.getClassName().replaceAll("\\.", "_") + "Network";
+ }
+
+ private String generateSource() {
+ createClassDeclaration();
+
+ ObjectTypeNodeParser parser = new ObjectTypeNodeParser(objectTypeNode);
+
+ // create declarations
+ DeclarationsHandler declarations = new DeclarationsHandler(builder);
+ parser.accept(declarations);
+
+ // we need the hashed declarations when creating the constructor
+ Collection<HashedAlphasDeclaration> hashedAlphaDeclarations = declarations.getHashedAlphaDeclarations();
+
+ createConstructor(hashedAlphaDeclarations);
+
+ // create set node method
+ SetNodeReferenceHandler setNode = new SetNodeReferenceHandler(builder);
+ parser.accept(setNode);
+
+ // create assert method
+ AssertHandler assertHandler = new AssertHandler(builder, className, hashedAlphaDeclarations.size() > 0);
+ parser.accept(assertHandler);
+
+ // end of class
+ builder.append("}").append(NEWLINE);
+
+ return builder.toString();
+ }
+
+ /**
+ * This method will output the package statement, followed by the opening of the class declaration
+ */
+ private void createClassDeclaration() {
+ builder.append("package ").append(PACKAGE_NAME).append(");").append(NEWLINE);
+ builder.append("public class ").append(generatedClassSimpleName).append(" extends ").
+ append(CompiledNetwork.class.getName()).append("{ ").append(NEWLINE);
+ }
+
+ /**
+ * Creates the constructor for the generated class. If the hashedAlphaDeclarations is empty, it will just
+ * output a empty default constructor; if it is not, the constructor will contain code to fill the hash
+ * alpha maps with the values and node ids.
+ *
+ * @param hashedAlphaDeclarations declarations used for creating statements to populate the hashed alpha
+ * maps for the generate class
+ */
+ private void createConstructor(Collection<HashedAlphasDeclaration> hashedAlphaDeclarations) {
+ builder.append("public ").append(generatedClassSimpleName).append("() {").append(NEWLINE);
+
+ // for each hashed alpha, we need to fill in the map member variable with the hashed values to node Ids
+ for (HashedAlphasDeclaration declaration : hashedAlphaDeclarations) {
+ String mapVariableName = declaration.getVariableName();
+
+ for (Object hashedValue : declaration.getHashedValues()) {
+ Object value = hashedValue;
+ // need to quote value if it is a string
+ if (declaration.getValueType() == ValueType.STRING_TYPE) {
+ value = "\"" + value + "\"";
+ }
+
+ String nodeId = declaration.getNodeId(hashedValue);
+
+ // generate the map.put(hashedValue, nodeId) call
+ builder.append(mapVariableName).append(".put(").append(value).append(", ").append(nodeId).append(");");
+ builder.append(NEWLINE);
+ }
+ }
+
+ builder.append("}").append(NEWLINE);
+ }
+
+ /**
+ * Returns the fully qualified name of the generated subclass of {@link org.drools.reteoo.compiled.CompiledNetwork}
+ *
+ * @return name of generated class
+ */
+ private String getName() {
+ return getPackageName() + "." + generatedClassSimpleName;
+ }
+
+ /**
+ * Returns the fully qualified binary name of the generated subclass of {@link org.drools.reteoo.compiled.CompiledNetwork}
+ *
+ * @return binary name of generated class
+ */
+ private String getBinaryName() {
+ return BINARY_PACKAGE_NAME + "." + generatedClassSimpleName + ".class";
+ }
+
+ private String getPackageName() {
+ return PACKAGE_NAME;
+ }
+
+ /**
+ * Creates a {@link CompiledNetwork} for the specified {@link ObjectTypeNode}. The {@link PackageBuilder} is used
+ * to compile the generated source and load the class.
+ *
+ * @param pkgBuilder builder used to compile and load class
+ * @param objectTypeNode OTN we are generating a compiled network for
+ * @return CompiledNetwork
+ */
+ public static CompiledNetwork compile(PackageBuilder pkgBuilder, ObjectTypeNode objectTypeNode) {
+ if (objectTypeNode == null) {
+ throw new IllegalArgumentException("ObjectTypeNode cannot be null!");
+ }
+ if (pkgBuilder == null) {
+ throw new IllegalArgumentException("PackageBuilder cannot be null!");
+ }
+ ObjectTypeNodeCompiler compiler = new ObjectTypeNodeCompiler(objectTypeNode);
+
+ String packageName = compiler.getPackageName();
+
+ PackageRegistry pkgReg = pkgBuilder.getPackageRegistry(packageName);
+ if (pkgReg == null) {
+ pkgBuilder.addPackage(new PackageDescr(packageName));
+ pkgReg = pkgBuilder.getPackageRegistry(packageName);
+ }
+
+ String source = compiler.generateSource();
+ String generatedSourceName = compiler.getName();
+
+ JavaDialect dialect = (JavaDialect) pkgReg.getDialectCompiletimeRegistry().getDialect("java");
+ dialect.addSrc(compiler.getBinaryName(), source.getBytes());
+ pkgBuilder.compileAll();
+ pkgBuilder.updateResults();
+
+ CompiledNetwork network;
+ try {
+ network = (CompiledNetwork) Class.forName(generatedSourceName, true, pkgBuilder.getRootClassLoader()).newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("This is a bug. Please contact the development team", e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("This is a bug. Please contact the development team", e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException("This is a bug. Please contact the development team", e);
+ }
+
+ return network;
+ }
+}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/manners/MannersBenchmark.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/manners/MannersBenchmark.java 2009-07-17 01:09:09 UTC (rev 28124)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/manners/MannersBenchmark.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -1,75 +1,78 @@
package org.drools.integrationtests.manners;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.StringTokenizer;
-
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
import org.drools.common.InternalRuleBase;
import org.drools.compiler.PackageBuilder;
-import org.drools.reteoo.AlphaNetworkCompiler;
import org.drools.reteoo.ObjectTypeNode;
+import org.drools.reteoo.compiled.CompiledNetwork;
+import org.drools.reteoo.compiled.ObjectTypeNodeCompiler;
import org.drools.rule.Package;
+import java.io.*;
+import java.util.*;
+
public class MannersBenchmark {
- /** Number of guests at the dinner (default: 16). */
- private int numGuests = 16;
+ /**
+ * Number of guests at the dinner (default: 16).
+ */
+ private int numGuests = 16;
- /** Number of seats at the table (default: 16). */
- private int numSeats = 16;
+ /**
+ * Number of seats at the table (default: 16).
+ */
+ private int numSeats = 16;
- /** Minimum number of hobbies each guest should have (default: 2). */
+ /**
+ * Minimum number of hobbies each guest should have (defaJavaCompilerFactoryult: 2).
+ */
private int minHobbies = 2;
- /** Maximun number of hobbies each guest should have (default: 3). */
+ /**
+ * Maximun number of hobbies each guest should have (default: 3).
+ */
private int maxHobbies = 3;
public static void main(final String[] args) throws Exception {
PackageBuilder builder = new PackageBuilder();
- builder.addPackageFromDrl( new InputStreamReader( MannersBenchmark.class.getResourceAsStream( "manners.drl" ) ) );
+ builder.addPackageFromDrl(new InputStreamReader(MannersBenchmark.class.getResourceAsStream("manners.drl")));
Package pkg = builder.getPackage();
// add the package to a rulebase
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
- ruleBase.addPackage( pkg );
-
- AlphaNetworkCompiler compiler = new AlphaNetworkCompiler();
-
- for(ObjectTypeNode node : ( (InternalRuleBase) ruleBase).getRete().getObjectTypeNodes() ){
- compiler.compile( node );
+ ruleBase.addPackage(pkg);
+
+ for (ObjectTypeNode node : ((InternalRuleBase) ruleBase).getRete().getObjectTypeNodes()) {
+ CompiledNetwork compiledNetwork = ObjectTypeNodeCompiler.compile(builder, node);
+ node.setCompiledNetwork(compiledNetwork);
}
-// StatefulSession session = ruleBase.newStatefulSession();
-//
-// String filename;
-// if ( args.length != 0 ) {
-// String arg = args[0];
-// filename = arg;
-// } else {
-// filename = "manners128.dat";
-// }
-//
-// InputStream is = MannersBenchmark.class.getResourceAsStream( filename );
-// List list = getInputObjects( is );
-// for ( Iterator it = list.iterator(); it.hasNext(); ) {
-// Object object = it.next();
-// session.insert( object );
-// }
-//
-// session.insert( new Count( 1 ) );
-//
-// long start = System.currentTimeMillis();
-// session.fireAllRules();
-// System.err.println( System.currentTimeMillis() - start );
-// session.dispose();
+ String filename;
+ if (args.length != 0) {
+ String arg = args[0];
+ filename = arg;
+ } else {
+ filename = "manners128.dat";
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ InputStream is = MannersBenchmark.class.getResourceAsStream(filename);
+ List list = getInputObjects(is);
+ StatefulSession session = ruleBase.newStatefulSession();
+
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ Object object = it.next();
+ session.insert(object);
+ }
+
+ session.insert(new Count(1));
+
+ long start = System.currentTimeMillis();
+ session.fireAllRules();
+ System.err.println(System.currentTimeMillis() - start);
+ session.dispose();
+ }
}
/**
@@ -79,50 +82,50 @@
protected static List getInputObjects(InputStream inputStream) throws IOException {
List list = new ArrayList();
- BufferedReader br = new BufferedReader( new InputStreamReader( inputStream ) );
+ BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
- while ( (line = br.readLine()) != null ) {
- if ( line.trim().length() == 0 || line.trim().startsWith( ";" ) ) {
+ while ((line = br.readLine()) != null) {
+ if (line.trim().length() == 0 || line.trim().startsWith(";")) {
continue;
}
- StringTokenizer st = new StringTokenizer( line,
- "() " );
+ StringTokenizer st = new StringTokenizer(line,
+ "() ");
String type = st.nextToken();
- if ( "guest".equals( type ) ) {
- if ( !"name".equals( st.nextToken() ) ) {
- throw new IOException( "expected 'name' in: " + line );
+ if ("guest".equals(type)) {
+ if (!"name".equals(st.nextToken())) {
+ throw new IOException("expected 'name' in: " + line);
}
String name = st.nextToken();
- if ( !"sex".equals( st.nextToken() ) ) {
- throw new IOException( "expected 'sex' in: " + line );
+ if (!"sex".equals(st.nextToken())) {
+ throw new IOException("expected 'sex' in: " + line);
}
String sex = st.nextToken();
- if ( !"hobby".equals( st.nextToken() ) ) {
- throw new IOException( "expected 'hobby' in: " + line );
+ if (!"hobby".equals(st.nextToken())) {
+ throw new IOException("expected 'hobby' in: " + line);
}
String hobby = st.nextToken();
- Guest guest = new Guest( name,
- Sex.resolve( sex ),
- Hobby.resolve( hobby ) );
+ Guest guest = new Guest(name,
+ Sex.resolve(sex),
+ Hobby.resolve(hobby));
- list.add( guest );
+ list.add(guest);
}
- if ( "last_seat".equals( type ) ) {
- if ( !"seat".equals( st.nextToken() ) ) {
- throw new IOException( "expected 'seat' in: " + line );
+ if ("last_seat".equals(type)) {
+ if (!"seat".equals(st.nextToken())) {
+ throw new IOException("expected 'seat' in: " + line);
}
- list.add( new LastSeat( new Integer( st.nextToken() ).intValue() ) );
+ list.add(new LastSeat(new Integer(st.nextToken()).intValue()));
}
- if ( "context".equals( type ) ) {
- if ( !"state".equals( st.nextToken() ) ) {
- throw new IOException( "expected 'state' in: " + line );
+ if ("context".equals(type)) {
+ if (!"state".equals(st.nextToken())) {
+ throw new IOException("expected 'state' in: " + line);
}
- list.add( new Context( st.nextToken() ) );
+ list.add(new Context(st.nextToken()));
}
}
inputStream.close();
@@ -131,7 +134,7 @@
}
private InputStream generateData() {
- final String LINE_SEPARATOR = System.getProperty( "line.separator" );
+ final String LINE_SEPARATOR = System.getProperty("line.separator");
StringWriter writer = new StringWriter();
@@ -143,42 +146,42 @@
// init hobbies
List hobbyList = new ArrayList();
- for ( int i = 1; i <= maxHobbies; i++ ) {
- hobbyList.add( "h" + i );
+ for (int i = 1; i <= maxHobbies; i++) {
+ hobbyList.add("h" + i);
}
Random rnd = new Random();
- for ( int i = 1; i <= numGuests; i++ ) {
+ for (int i = 1; i <= numGuests; i++) {
char sex = rnd.nextBoolean() ? 'm' : 'f';
- if ( sex == 'm' && maleCount == maxMale ) {
+ if (sex == 'm' && maleCount == maxMale) {
sex = 'f';
}
- if ( sex == 'f' && femaleCount == maxFemale ) {
+ if (sex == 'f' && femaleCount == maxFemale) {
sex = 'm';
}
- if ( sex == 'm' ) {
+ if (sex == 'm') {
maleCount++;
}
- if ( sex == 'f' ) {
+ if (sex == 'f') {
femaleCount++;
}
- List guestHobbies = new ArrayList( hobbyList );
+ List guestHobbies = new ArrayList(hobbyList);
- int numHobbies = minHobbies + rnd.nextInt( maxHobbies - minHobbies + 1 );
- for ( int j = 0; j < numHobbies; j++ ) {
- int hobbyIndex = rnd.nextInt( guestHobbies.size() );
- String hobby = (String) guestHobbies.get( hobbyIndex );
- writer.write( "(guest (name n" + i + ") (sex " + sex + ") (hobby " + hobby + "))" + LINE_SEPARATOR );
- guestHobbies.remove( hobbyIndex );
+ int numHobbies = minHobbies + rnd.nextInt(maxHobbies - minHobbies + 1);
+ for (int j = 0; j < numHobbies; j++) {
+ int hobbyIndex = rnd.nextInt(guestHobbies.size());
+ String hobby = (String) guestHobbies.get(hobbyIndex);
+ writer.write("(guest (name n" + i + ") (sex " + sex + ") (hobby " + hobby + "))" + LINE_SEPARATOR);
+ guestHobbies.remove(hobbyIndex);
}
}
- writer.write( "(last_seat (seat " + numSeats + "))" + LINE_SEPARATOR );
+ writer.write("(last_seat (seat " + numSeats + "))" + LINE_SEPARATOR);
- writer.write( LINE_SEPARATOR );
- writer.write( "(context (state start))" + LINE_SEPARATOR );
+ writer.write(LINE_SEPARATOR);
+ writer.write("(context (state start))" + LINE_SEPARATOR);
- return new ByteArrayInputStream( writer.getBuffer().toString().getBytes() );
+ return new ByteArrayInputStream(writer.getBuffer().toString().getBytes());
}
}
Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNetworkCompiler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNetworkCompiler.java 2009-07-17 01:09:09 UTC (rev 28124)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNetworkCompiler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -1,166 +0,0 @@
-package org.drools.reteoo;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-import org.drools.util.Iterator;
-import org.drools.util.ObjectHashMap;
-import org.drools.util.ObjectHashMap.ObjectEntry;
-
-public class AlphaNetworkCompiler {
- private StringBuilder builder;
-
- public void compile(ObjectTypeNode objectTypeNode) {
- builder = new StringBuilder();
- builder.append( "public class Compiled" + objectTypeNode.getObjectType() + "AlphaNetwork implements ObjectSink { \n" );
-
- createVars( objectTypeNode.getSinkPropagator().getSinks(), 4 );
-
- builder.append( " public void assertObject(....) { \n");
-
- compileAlphaNodes( objectTypeNode.getSinkPropagator(),
- 8 );
-
- builder.append( " } \n" );
- builder.append( "} \n" );
-
- System.out.println( builder.toString() );
- }
-
- public void createVars(ObjectSink[] sinks,
- int indent) {
- for ( ObjectSink sink : sinks ) {
- if ( sink instanceof AlphaNode ) {
- AlphaNode alphaNode = (AlphaNode) sink;
- builder.append( getIndent( indent ) + "AlphaNodeFieldConstraint alphaNodeConstraint" + alphaNode.getId() + ";\n" );
- createVars( alphaNode.getSinkPropagator().getSinks(), indent );
- } else if ( sink instanceof BetaNode ) {
- BetaNode betaNode = (BetaNode) sink;
- builder.append( getIndent( indent ) + "ObjectSink sink" + betaNode.getId() + ";\n" );
- } else if ( sink instanceof LeftInputAdapterNode ) {
- LeftInputAdapterNode liaNode = (LeftInputAdapterNode) sink;
- builder.append( getIndent( indent ) + "ObjectSink sink" + liaNode.getId() + ";\n" );
- }
- }
- }
-
- public void compileAlphaNodes(ObjectSinkPropagator adapter,
- int indent) {
- if ( adapter instanceof SingleObjectSinkAdapter ) {
- compileAlphaNodeSingleConstraint( (SingleObjectSinkAdapter) adapter,
- indent );
- } else if ( adapter instanceof CompositeObjectSinkAdapter ) {
- compileAlphaNodeCompositeConstraint( (CompositeObjectSinkAdapter) adapter,
- indent );
- }
- }
-
- private void compileAlphaNodeCompositeConstraint(CompositeObjectSinkAdapter adapter,
- int indent) {
- ObjectSinkNodeList sinks = adapter.getHashableSinks();
- if ( sinks != null ) {
- for ( ObjectSinkNode sink = sinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
- compileAlphaNodeSingleConstraint( sink,
- indent );
- }
- }
-
- sinks = adapter.getOthers();
- if ( sinks != null ) {
- for ( ObjectSinkNode sink = sinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
- compileAlphaNodeSingleConstraint( sink,
- indent );
- }
- }
-
- ObjectHashMap map = adapter.getHashedSinkMap();
- if ( map != null ) {
- ObjectEntry[] entries = new ObjectEntry[map.size()];
- Iterator it = map.iterator();
- int i = 0;
- for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
- entries[i++] = entry;
- }
-
- // we sort as switch works faster with ordered cases
- Arrays.sort( entries,
- new Comparator() {
- public int compare(Object o1,
- Object o2) {
- ObjectEntry entry1 = (ObjectEntry) o1;
- ObjectEntry entry2 = (ObjectEntry) o2;
- return ((ObjectSink) entry1.getValue()).getId() - ((ObjectSink) entry2.getValue()).getId();
- }
-
- } );
-
- //final Iterator it = map.newIterator();
- builder.append( getIndent( indent ) + "HashKey key = new HashKey(handle);\n" );
- builder.append( getIndent( indent ) + "swtich ((ObjectSink)this.hashedSinkedMap(key)).getId() {\n" );
- for ( ObjectEntry entry : entries ) {
- ObjectSink sink = (ObjectSink) entry.getValue();
- builder.append( getIndent( indent + 4 ) + "case " + sink.getId() + ": {\n" );
- //builder.append( getIndent( indent + 8 ) + "sink" + sink.getId() + ".assertRight(handle, wm, context);\n" );
-
- if (sink instanceof AlphaNode ) {
- compileAlphaNodes( ((AlphaNode)sink).getSinkPropagator(),
- indent + 8 );
- }
-
- builder.append( getIndent( indent + 4 )+ "};\n" );
- }
- builder.append( getIndent( indent ) + "};\n" );
- }
-
- }
-
- public void compileAlphaNodeSingleConstraint(SingleObjectSinkAdapter adapter,
- int indent) {
- compileAlphaNodeSingleConstraint( adapter.getSinks()[0],
- indent );
- }
-
- public void compileAlphaNodeSingleConstraint(ObjectSink sink,
- int indent) {
- if ( sink instanceof AlphaNode ) {
- AlphaNode alphaNode = (AlphaNode) sink;
- builder.append( getIndent( indent ) + "if ( alphaNodeConstraint" + alphaNode.getId() + ".isAllowed(handle, wm) ) {\n" );
- compileAlphaNodes( alphaNode.getSinkPropagator(),
- indent + 4 );
- builder.append( getIndent( indent ) + "}\n" );
- } else if ( sink instanceof BetaNode ) {
- BetaNode betaNode = (BetaNode) sink;
- builder.append( getIndent( indent ) + "sink" + betaNode.getId() + ".assertRight(handle, wm, context);\n" );
- } else if ( sink instanceof LeftInputAdapterNode ) {
- LeftInputAdapterNode liaNode = (LeftInputAdapterNode) sink;
- builder.append( getIndent( indent ) + "sink" + liaNode.getId() + ".assertRight(handle, wm, context);\n" );
- }
- }
-
- public void compileAlphaNodeCompositeConstraint(ObjectSink sink,
- int indent) {
- if ( sink instanceof AlphaNode ) {
- AlphaNode alphaNode = (AlphaNode) sink;
- builder.append( getIndent( indent ) + "if ( alphaNodeConstraint" + alphaNode.getId() + ".isAllowed(handle, wm) ) {\n" );
- compileAlphaNodes( alphaNode.getSinkPropagator(),
- indent + 4 );
- builder.append( getIndent( indent ) + "}\n" );
- } else if ( sink instanceof BetaNode ) {
- BetaNode betaNode = (BetaNode) sink;
- builder.append( getIndent( indent ) + "sink" + betaNode.getId() + ".assertRight(handle, wm, context);\n" );
- } else if ( sink instanceof LeftInputAdapterNode ) {
- LeftInputAdapterNode liaNode = (LeftInputAdapterNode) sink;
- builder.append( getIndent( indent ) + "sink" + liaNode.getId() + ".assertRight(handle, wm, context);\n" );
- }
- }
-
- private String getIndent(int indent) {
- char[] spaces = new char[indent];
- for ( int i = 0; i < spaces.length; i++ ) {
- spaces[i] = ' ';
- }
-
- return new String( spaces );
- }
-
-}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AbstractCompilerHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AbstractCompilerHandler.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AbstractCompilerHandler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,59 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.Sink;
+
+/**
+ * This handler is used as a base class for all {@link org.drools.reteoo.compiled.NetworkHandler}s used for
+ * generating a compiled network. It provides methods to return the variable type and names used for storing
+ * refernces to different {@link org.drools.common.NetworkNode}s and variable names for {@link ClassFieldReader}s.
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+abstract class AbstractCompilerHandler extends NetworkHandlerAdaptor {
+ protected static final String NEWLINE = "\n";
+
+ private static final String MAP_VARIABLE_NAME_SUFFIX = "ToNodeId";
+
+ protected Class<?> getVariableType(AlphaNode alphaNode) {
+
+ // for alphas, we use the constraint of the alpha for the declaration
+ return alphaNode.getConstraint().getClass();
+ }
+
+ protected Class<?> getVariableType(Sink sink) {
+
+ return sink.getClass();
+ }
+
+ protected String getVariableName(AlphaNode alphaNode) {
+ Class<?> variableType = getVariableType(alphaNode);
+
+ return getVariableName(variableType, alphaNode.getId());
+ }
+
+ protected String getVariableName(Sink sink) {
+ Class<?> variableType = getVariableType(sink);
+
+ return getVariableName(variableType, sink.getId());
+ }
+
+ protected String getVariableName(ClassFieldReader fieldReader) {
+ return fieldReader.getFieldName() + MAP_VARIABLE_NAME_SUFFIX;
+ }
+
+ /**
+ * Returns a variable name based on the simple name of the specified class appended with the specified
+ * nodeId.
+ *
+ * @param clazz class whose simple name is lowercased and user as the prefix of the variable name
+ * @param nodeId id of {@link org.drools.common.NetworkNode}
+ * @return variable name
+ * @see Class#getSimpleName()
+ */
+ private String getVariableName(Class clazz, int nodeId) {
+ String type = clazz.getSimpleName();
+ return Character.toLowerCase(type.charAt(0)) + type.substring(1) + nodeId;
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AssertHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AssertHandler.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/AssertHandler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,145 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.BetaNode;
+import org.drools.reteoo.LeftInputAdapterNode;
+import org.drools.reteoo.ObjectTypeNode;
+import org.drools.spi.PropagationContext;
+
+/**
+ * todo: document
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+class AssertHandler extends AbstractCompilerHandler {
+ private static final String LOCAL_FACT_VAR_NAME = "fact";
+
+ private static final String FACT_HANDLE_PARAM_TYPE = InternalFactHandle.class.getName();
+ private static final String PROP_CONTEXT_PARAM_TYPE = PropagationContext.class.getName();
+ private static final String WORKING_MEMORY_PARAM_TYPE = InternalWorkingMemory.class.getName();
+
+ private static final String FACT_HANDLE_PARAM_NAME = "handle";
+ private static final String PROP_CONTEXT_PARAM_NAME = "context";
+ private static final String WORKING_MEMORY_PARAM_NAME = "wm";
+
+ private static final String ASSERT_METHOD_SIGNATURE = "public final void assertObject("
+ + FACT_HANDLE_PARAM_TYPE + " " + FACT_HANDLE_PARAM_NAME + ","
+ + PROP_CONTEXT_PARAM_TYPE + " " + PROP_CONTEXT_PARAM_NAME + ","
+ + WORKING_MEMORY_PARAM_TYPE + " " + WORKING_MEMORY_PARAM_NAME + "){";
+
+ /**
+ * This flag is used to instruct the AssertHandler to tell it to generate a local varible
+ * in the {@link org.drools.reteoo.compiled.CompiledNetwork#assertObject} for holding the value returned
+ * from the {@link org.drools.common.InternalFactHandle#getObject()}.
+ *
+ * This is only needed if there is at least 1 set of hashed alpha nodes in the network
+ */
+ private final boolean alphaNetContainsHashedField;
+
+ private final StringBuilder builder;
+ private final String factClassName;
+
+ AssertHandler(StringBuilder builder, String factClassName) {
+ this(builder, factClassName, false);
+ }
+
+ AssertHandler(StringBuilder builder, String factClassName, boolean alphaNetContainsHashedField) {
+ this.builder = builder;
+ this.factClassName = factClassName;
+ this.alphaNetContainsHashedField = alphaNetContainsHashedField;
+ }
+
+ @Override
+ public void startObjectTypeNode(ObjectTypeNode objectTypeNode) {
+ builder.append(ASSERT_METHOD_SIGNATURE).append(NEWLINE);
+
+ // we only need to create a reference to the object, not handle, if there is a hashed alpha in the network
+ if (alphaNetContainsHashedField) {
+ // example of what this will look like
+ // ExampleFact fact = (ExampleFact) handle.getObject();
+ builder.append(factClassName).append(" ").append(LOCAL_FACT_VAR_NAME).
+ append(" = (").append(factClassName).append(")").
+ append(FACT_HANDLE_PARAM_NAME).append(".getObject();").
+ append(NEWLINE);
+ }
+ }
+
+ @Override
+ public void startBetaNode(BetaNode betaNode) {
+ builder.append(getVariableName(betaNode)).append(".assertObject(").
+ append(FACT_HANDLE_PARAM_NAME).append(",").
+ append(PROP_CONTEXT_PARAM_NAME).append(",").
+ append(WORKING_MEMORY_PARAM_NAME).append(");").append(NEWLINE);
+ }
+
+ @Override
+ public void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+ builder.append(getVariableName(leftInputAdapterNode)).append(".assertObject(").
+ append(FACT_HANDLE_PARAM_NAME).append(",").
+ append(PROP_CONTEXT_PARAM_NAME).append(",").
+ append(WORKING_MEMORY_PARAM_NAME).append(");").append(NEWLINE);
+ }
+
+ @Override
+ public void startNonHashedAlphaNode(AlphaNode alphaNode) {
+ builder.append("if ( ").append(getVariableName(alphaNode)).
+ append(".isAllowed(").append(FACT_HANDLE_PARAM_NAME).append(",").
+ append(WORKING_MEMORY_PARAM_NAME).append(", ").
+ append(getVariableName(alphaNode)).append(".createContextEntry()) ) {").append(NEWLINE);
+
+ }
+
+ @Override
+ public void endNonHashedAlphaNode(AlphaNode alphaNode) {
+ // close if statement
+ builder.append("}").append(NEWLINE);
+ }
+
+ @Override
+ public void startHashedAlphaNodes(ClassFieldReader hashedFieldReader) {
+ String attributeName = hashedFieldReader.getFieldName();
+ String localVariableName = attributeName + "NodeId";
+
+ // todo get accessor smarter because of booleans. Note that right now booleans wouldn't be hashed
+ String attributeGetterName = "get" + Character.toTitleCase(attributeName.charAt(0)) + attributeName.substring(1);
+
+ // get the attribute from the fact that we are switching over
+ builder.append("Integer ").append(localVariableName);
+ // todo we are casting to Integer because generics aren't supported
+ builder.append(" = (Integer)").append(getVariableName(hashedFieldReader)).append(".get(").
+ append(LOCAL_FACT_VAR_NAME).append(".").append(attributeGetterName)
+ .append("());").append(NEWLINE);
+
+ // ensure that the value is present in the node map
+ builder.append("if(").append(localVariableName).append(" != null) {").append(NEWLINE);
+ // todo we had the .intValue() because JANINO has a problem with it
+ builder.append("switch(").append(localVariableName).append(".intValue()) {").append(NEWLINE);
+ }
+
+ @Override
+ public void startHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+ builder.append("case ").append(hashedAlpha.getId()).append(" : ").append(NEWLINE);
+ }
+
+ @Override
+ public void endHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+ builder.append("break;").append(NEWLINE);
+ }
+
+ @Override
+ public void endHashedAlphaNodes(ClassFieldReader hashedFieldReader) {
+ // close switch statement
+ builder.append("}").append(NEWLINE);
+ // and if statement for ensuring non-null
+ builder.append("}").append(NEWLINE);
+ }
+
+ @Override
+ public void endObjectTypeNode(ObjectTypeNode objectTypeNode) {
+ // close the assertObject method
+ builder.append("}").append(NEWLINE);
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/CompiledNetwork.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/CompiledNetwork.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/CompiledNetwork.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,116 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.common.NetworkNode;
+import org.drools.common.RuleBasePartitionId;
+import org.drools.reteoo.*;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * This is the base type for all generated classes that that represent a "compiled" portion of the RETE network.
+ * By compiled we mean IF statements, switch statements, etc. as opposed to nodes, propagators, etc.
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+public abstract class CompiledNetwork implements ObjectSink {
+
+ private ObjectTypeNode objectTypeNode;
+
+ /**
+ * Returns the unique id that represents the node in the Rete network
+ *
+ * @return unique int value
+ */
+ public int getId() {
+ return objectTypeNode.getId();
+ }
+
+ /**
+ * Returns the partition ID to which this node belongs to
+ *
+ * @return partition id
+ */
+ public RuleBasePartitionId getPartitionId() {
+ return objectTypeNode.getPartitionId();
+ }
+
+ /**
+ * The object implements the writeExternal method to save its contents
+ * by calling the methods of DataOutput for its primitive values or
+ * calling the writeObject method of ObjectOutput for objects, strings,
+ * and arrays.
+ *
+ * @param out the stream to write the object to
+ * @throws java.io.IOException Includes any I/O exceptions that may occur
+ * @serialData Overriding methods should use this tag to describe
+ * the data layout of this Externalizable object.
+ * List the sequence of element types and, if possible,
+ * relate the element to a public/protected field and/or
+ * method of this Externalizable class.
+ */
+ public void writeExternal(ObjectOutput out) throws IOException {
+ // todo is this needed??
+ }
+
+ /**
+ * The object implements the readExternal method to restore its
+ * contents by calling the methods of DataInput for primitive
+ * types and readObject for objects, strings and arrays. The
+ * readExternal method must read the values in the same sequence
+ * and with the same types as were written by writeExternal.
+ *
+ * @param in the stream to read data from in order to restore the object
+ * @throws java.io.IOException if I/O errors occur
+ * @throws ClassNotFoundException If the class for an object being
+ * restored cannot be found.
+ */
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ // todo is this needed??
+ }
+
+ /**
+ * Sets the OTN for this network. Calling this method will set all variables in the generated subclasses
+ * by walking the {@link org.drools.reteoo.ObjectTypeNode} using a {@link ObjectTypeNodeParser}.
+ * @param objectTypeNode node for whom this network was created
+ */
+ public final void setObjectTypeNode(final ObjectTypeNode objectTypeNode) {
+ this.objectTypeNode = objectTypeNode;
+
+ NodeReferenceSetter setter= new NodeReferenceSetter();
+ ObjectTypeNodeParser parser = new ObjectTypeNodeParser(objectTypeNode);
+ parser.accept(setter);
+ }
+
+ /**
+ * Generated subclasses need to implement this method to set member variables based on the specified
+ * NetworkNode.
+ *
+ * @param networkNode node to set to set
+ */
+ protected abstract void setNetworkNodeReference(NetworkNode networkNode);
+
+ /**
+ * Handler implementation to call {@link CompiledNetwork#setNetworkNodeReference} for each node
+ * encountered in the network.
+ */
+ private class NodeReferenceSetter extends NetworkHandlerAdaptor {
+
+ public void startNonHashedAlphaNode(AlphaNode alphaNode) {
+ setNetworkNodeReference(alphaNode);
+ }
+
+ public void startBetaNode(BetaNode betaNode) {
+ setNetworkNodeReference(betaNode);
+ }
+
+ public void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+ setNetworkNodeReference(leftInputAdapterNode);
+ }
+
+ public void startHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+ setNetworkNodeReference(hashedAlpha);
+ }
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/DeclarationsHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/DeclarationsHandler.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/DeclarationsHandler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,112 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.BetaNode;
+import org.drools.reteoo.LeftInputAdapterNode;
+import org.drools.reteoo.Sink;
+
+import java.util.*;
+
+/**
+ * This handler is used to create the member declarations section of a generated subclass of a {@link CompiledNetwork}.
+ * Currently we only create member variables for the following types of nodes:
+ * <p/>
+ * <li>Non-hashed {@link AlphaNode}s</li>
+ * <li>{@link LeftInputAdapterNode}s</li>
+ * <li>{@link BetaNode}s</li>
+ * <li>A {@link Map} for each set of hashed {@link AlphaNode}s. The keys are the hashed values, and the values are
+ * the IDs of the alphas</li>
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+class DeclarationsHandler extends AbstractCompilerHandler {
+ private static final String PRIVATE_MODIFIER = "private";
+
+ /**
+ * This field keeps track of the current set of hashed AlphaNodes for a ClassReader.
+ *
+ * @see #startHashedAlphaNodes(org.drools.base.ClassFieldReader)
+ * @see #startHashedAlphaNode(org.drools.reteoo.AlphaNode, Object)
+ */
+ private HashedAlphasDeclaration currentHashedAlpha;
+
+ private final StringBuilder builder;
+
+ /**
+ * Keeps track of all the ClassFieldReaders for hashed alphas, and the maps that contain hashed values/node ids
+ * for said alphas.
+ */
+ private final Collection<HashedAlphasDeclaration> hashedAlphaDeclarations;
+
+ DeclarationsHandler(StringBuilder builder) {
+ this.builder = builder;
+ this.hashedAlphaDeclarations = new LinkedList<HashedAlphasDeclaration>();
+ }
+
+ private String getVariableDeclaration(AlphaNode alphaNode) {
+ Class<?> variableType = getVariableType(alphaNode);
+ String variableName = getVariableName(alphaNode);
+ // comment for variable declaration is just the toString of the node
+ String comment = alphaNode.toString();
+
+ return PRIVATE_MODIFIER + " " + variableType.getName() + " " + variableName + "; // " + comment;
+ }
+
+ private String getVariableDeclaration(Sink sink) {
+ Class<?> declarationType = getVariableType(sink);
+ String variableName = getVariableName(sink);
+ // comment for variable declaration is just the toString of the node
+ String comment = sink.toString();
+
+ return PRIVATE_MODIFIER + " " + declarationType.getName() + " " + variableName + "; // " + comment;
+ }
+
+ private String getVariableDeclaration(ClassFieldReader fieldReader) {
+ Class<?> declarationType = Map.class;
+ Class<?> createType = HashMap.class;
+ String variableName = getVariableName(fieldReader);
+
+ // todo JANINO doesn't support generics
+ // return "private java.util.Map<Object,Integer> " + variableName + " = new java.util.HashMap<Object,Integer>();";
+ return PRIVATE_MODIFIER + " " + declarationType.getName() + " " + variableName
+ + " = new " + createType.getName() + "();";
+ }
+
+ Collection<HashedAlphasDeclaration> getHashedAlphaDeclarations() {
+ return Collections.unmodifiableCollection(hashedAlphaDeclarations);
+ }
+
+ @Override
+ public void startNonHashedAlphaNode(AlphaNode alphaNode) {
+ builder.append(getVariableDeclaration(alphaNode)).append(NEWLINE);
+ }
+
+ @Override
+ public void startBetaNode(BetaNode betaNode) {
+ builder.append(getVariableDeclaration(betaNode)).append(NEWLINE);
+ }
+
+ @Override
+ public void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+ builder.append(getVariableDeclaration(leftInputAdapterNode)).append(NEWLINE);
+ }
+
+ @Override
+ public void startHashedAlphaNodes(ClassFieldReader hashedFieldReader) {
+ // we create a new hashed alpha that will be used to keep track of the hashes values to node ID for each
+ // class field reader.
+ currentHashedAlpha = new HashedAlphasDeclaration(getVariableName(hashedFieldReader),
+ hashedFieldReader.getValueType());
+
+ // add the new declaration
+ hashedAlphaDeclarations.add(currentHashedAlpha);
+
+ builder.append(getVariableDeclaration(hashedFieldReader)).append(NEWLINE);
+ }
+
+ @Override
+ public void startHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+ currentHashedAlpha.add(hashedValue, String.valueOf(hashedAlpha.getId()));
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/HashedAlphasDeclaration.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/HashedAlphasDeclaration.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/HashedAlphasDeclaration.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,50 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ValueType;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * This class is used to hold information for Hashed {@link org.drools.reteoo.AlphaNode}s for generated subclasses
+ * of {@link CompiledNetwork}.
+ *
+ * @see org.drools.reteoo.compiled.DeclarationsHandler
+ */
+class HashedAlphasDeclaration {
+ private final String variableName;
+ private final ValueType valueType;
+
+ /**
+ * This map contains keys which are different values of the same field and the node id that of the
+ * {@link org.drools.common.NetworkNode} the value is from.
+ */
+ private final Map<Object, String> hashedValuesToNodeIds = new HashMap<Object, String>();
+
+ HashedAlphasDeclaration(String variableName,ValueType valueType) {
+ this.variableName = variableName;
+ this.valueType = valueType;
+ }
+
+ ValueType getValueType() {
+ return valueType;
+ }
+
+ String getVariableName() {
+ return variableName;
+ }
+
+ void add(Object hashedValue, String nodeId) {
+ hashedValuesToNodeIds.put(hashedValue, nodeId);
+ }
+
+ Collection<Object> getHashedValues() {
+ return Collections.unmodifiableSet(hashedValuesToNodeIds.keySet());
+ }
+
+ String getNodeId(Object hashedValue) {
+ return hashedValuesToNodeIds.get(hashedValue);
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandler.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,80 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.BetaNode;
+import org.drools.reteoo.LeftInputAdapterNode;
+import org.drools.reteoo.ObjectTypeNode;
+
+/**
+ * Receive notification of the logical parts of the RETE-OO network.
+ * todo: finish documenting
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+public interface NetworkHandler {
+
+ /**
+ * Receive notification of the beginning of an {@link org.drools.reteoo.ObjectTypeNode}
+ *
+ * <p>The Network parser will invoke this method only once, before any other event callback.</p>
+ *
+ * @param objectTypeNode the object type node
+ * @see #endObjectTypeNode(org.drools.reteoo.ObjectTypeNode)
+ */
+ void startObjectTypeNode(ObjectTypeNode objectTypeNode);
+
+ /**
+ * Receive notification of the a non-hashed {@link org.drools.reteoo.AlphaNode}.
+ *
+ * <p>The Parser will invoke this method at the beginning of every non-hashed Alpha in the Network;
+ * there will be a corresponding endNonHashedAlphaNode() event for every startNonHashedAlphaNode() event.
+ * All of the node's decendants will be reported, in order, before the corresponding endNonHashedAlphaNode()
+ * event.</p>
+ *
+ * @param alphaNode non-hashed AlphaNode
+ * @see #endNonHashedAlphaNode
+ */
+ void startNonHashedAlphaNode(AlphaNode alphaNode);
+
+ /**
+ * Receive notification of the end of a non-hashed {@link org.drools.reteoo.AlphaNode}.
+ *
+ * <p>The parser will invoke this method at the end of every alpha in the network; there will be a corresponding
+ * {@link #startNonHashedAlphaNode(org.drools.reteoo.AlphaNode)} event for every endNonHashedAlphaNode event.</p>
+ *
+ * @param alphaNode non-hashed AlphaNode
+ */
+ void endNonHashedAlphaNode(AlphaNode alphaNode);
+
+ void startBetaNode(BetaNode betaNode);
+
+ void endBetaNode(BetaNode betaNode);
+
+ void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode);
+
+ void endLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode);
+
+ /**
+ * Receive notification of the a group of hashed {@link org.drools.reteoo.AlphaNode}s.
+ *
+ * <p>The Parser will invoke this method at the beginning of every groups of hashed Alphas in the Network;
+ * there will be a corresponding {@link #endHashedAlphaNodes} event for every startHashedAlphaNodes() event.
+ *
+ * The actual alpha nodes will be reported via the {@link #startHashedAlphaNode} method, along with all of the
+ * node's decendants, in order, before the corresponding {@link #endHashedAlphaNode}
+ * event.</p>
+ *
+ * @param hashedFieldReader field reader that is used to access the hashed attribute
+ * @see #endHashedAlphaNodes
+ * @see #startHashedAlphaNode
+ */
+ void startHashedAlphaNodes(ClassFieldReader hashedFieldReader);
+
+ void endHashedAlphaNodes(ClassFieldReader hashedFieldReader);
+
+ void startHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue);
+
+ void endHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue);
+
+ void endObjectTypeNode(ObjectTypeNode objectTypeNode);
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandlerAdaptor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandlerAdaptor.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/NetworkHandlerAdaptor.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,70 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.BetaNode;
+import org.drools.reteoo.LeftInputAdapterNode;
+import org.drools.reteoo.ObjectTypeNode;
+
+/**
+ * An abstract adapter class for receiving network node events from the {@link org.drools.reteoo.compiled.ObjectTypeNodeParser}.
+ * The methods in this class are empty. This class exists as convenience for creating handler objects.
+ * <P>
+ * Extend this class to create a <code>NetworkHandler</code> and override the methods for the nodes of interest.
+ * (If you implement the {@link NetworkHandler} interface, you have to define all of the methods in it. This
+ * abstract class defines null methods for them all, so you can only have to define methods for events you care about.)
+ * <P>
+ * @see org.drools.reteoo.compiled.NetworkHandler
+ * @see org.drools.reteoo.compiled.ObjectTypeNodeParser
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+public class NetworkHandlerAdaptor implements NetworkHandler {
+ public void startObjectTypeNode(ObjectTypeNode objectTypeNode) {
+
+ }
+
+ public void startNonHashedAlphaNode(AlphaNode alphaNode) {
+
+ }
+
+ public void endNonHashedAlphaNode(AlphaNode alphaNode) {
+
+ }
+
+ public void startBetaNode(BetaNode betaNode) {
+
+ }
+
+ public void endBetaNode(BetaNode betaNode) {
+
+ }
+
+ public void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+
+ }
+
+ public void endLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+
+ }
+
+ public void startHashedAlphaNodes(ClassFieldReader hashedFieldReader) {
+
+ }
+
+ public void endHashedAlphaNodes(ClassFieldReader hashedFieldReader) {
+
+ }
+
+ public void startHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+
+ }
+
+ public void endHashedAlphaNode(AlphaNode hashedAlpha, Object hashedValue) {
+
+ }
+
+ public void endObjectTypeNode(ObjectTypeNode objectTypeNode) {
+
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeParser.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeParser.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/ObjectTypeNodeParser.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,202 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.base.ClassFieldReader;
+import org.drools.reteoo.*;
+import org.drools.rule.LiteralConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap;
+
+/**
+ * This class is used for reading an {@link ObjectTypeNode} using callbacks.
+ * <p/>
+ * The user defines a number of callback methods in a {@link NetworkHandler} that will be called when events occur
+ * during parsing. The events include :
+ * <li>ObjectTypeNode</li>
+ * <li>Non-hashed and hashed AlphaNodes</li>
+ * <li>BetaNodes</li>
+ * <li>LeftInputAdapterNodes</li>
+ * <p/>
+ * Events are fired when each of these network features are encountered, and again when the end of them is encountered.
+ * OTN parsing is unidirectional; previously parsed data cannot be re-read without starting the parsing operation again.
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+public class ObjectTypeNodeParser {
+
+ /**
+ * OTN we are parsing/traversing
+ */
+ private final ObjectTypeNode objectTypeNode;
+
+ /**
+ * Creates a new parser for the specified ObjectTypeNode
+ *
+ * @param objectTypeNode otn to parse
+ */
+ public ObjectTypeNodeParser(ObjectTypeNode objectTypeNode) {
+ this.objectTypeNode = objectTypeNode;
+ }
+
+ /**
+ * Parse the {@link #objectTypeNode}.
+ * <p/>
+ * <p>The application can use this method to instruct the OTN parser to begin parsing an {@link ObjectTypeNode}.</p>
+ * <p/>
+ * Once a parse is complete, an application may reuse the same Parser object, possibly with a different
+ * {@link NetworkHandler}.</p>
+ *
+ * @param handler handler that will receieve the events generated by this parser
+ * @see NetworkHandler
+ */
+ public void accept(NetworkHandler handler) {
+ ObjectSinkPropagator propagator = objectTypeNode.getSinkPropagator();
+
+ handler.startObjectTypeNode(objectTypeNode);
+ traversePropagator(propagator, handler);
+ handler.endObjectTypeNode(objectTypeNode);
+ }
+
+ private void traversePropagator(ObjectSinkPropagator propagator, NetworkHandler handler) {
+ if (propagator instanceof SingleObjectSinkAdapter) {
+ // we know there is only a single child sink for this propagator
+ ObjectSink sink = propagator.getSinks()[0];
+
+ traverseSink(sink, handler);
+ } else if (propagator instanceof CompositeObjectSinkAdapter) {
+ CompositeObjectSinkAdapter composite = (CompositeObjectSinkAdapter) propagator;
+
+ traverseSinkLisk(composite.getHashableSinks(), handler);
+ traverseSinkLisk(composite.getOthers(), handler);
+ traverseHashedAlphaNodes(composite.getHashedSinkMap(), handler);
+ }
+ }
+
+ private void traversePropagator(LeftTupleSinkPropagator propagator, NetworkHandler handler) {
+ if (propagator instanceof SingleLeftTupleSinkAdapter) {
+ // we know there is only a single child sink for this propagator
+ LeftTupleSink sink = propagator.getSinks()[0];
+
+ traverseSink(sink, handler);
+ } else if (propagator instanceof CompositeLeftTupleSinkAdapter) {
+ CompositeLeftTupleSinkAdapter composite = (CompositeLeftTupleSinkAdapter) propagator;
+
+ LeftTupleSink[] sinks = composite.getSinks();
+ traverseSinkLisk(sinks, handler);
+ }
+ }
+
+ private void traverseSinkLisk(ObjectSinkNodeList sinks, NetworkHandler handler) {
+ if (sinks != null) {
+ for (ObjectSinkNode sink = sinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) {
+
+ traverseSink(sink, handler);
+ }
+ }
+ }
+
+ private void traverseSinkLisk(LeftTupleSink[] sinks, NetworkHandler handler) {
+ if (sinks != null) {
+ for (int sinkIndex = 0; sinkIndex < sinks.length; ++sinkIndex) {
+ traverseSink(sinks[sinkIndex], handler);
+ }
+ }
+ }
+
+ private void traverseHashedAlphaNodes(ObjectHashMap hashedAlphaNodes, NetworkHandler handler) {
+ if (hashedAlphaNodes != null && hashedAlphaNodes.size() > 0) {
+ AlphaNode firstAlpha = getFirstAlphaNode(hashedAlphaNodes);
+ ClassFieldReader hashedFieldReader = getClassFieldReaderForHashedAlpha(firstAlpha);
+
+ // start the hashed alphas
+ handler.startHashedAlphaNodes(hashedFieldReader);
+
+ Iterator iter = hashedAlphaNodes.iterator();
+ for (ObjectHashMap.ObjectEntry entry = (ObjectHashMap.ObjectEntry) iter.next(); entry != null; entry = (ObjectHashMap.ObjectEntry) iter.next()) {
+ CompositeObjectSinkAdapter.HashKey hashKey = (CompositeObjectSinkAdapter.HashKey) entry.getKey();
+ AlphaNode alphaNode = (AlphaNode) entry.getValue();
+
+ handler.startHashedAlphaNode(alphaNode, hashKey.getObjectValue());
+ // traverse the propagator for each alpha
+ traversePropagator(alphaNode.getSinkPropagator(), handler);
+
+ handler.endHashedAlphaNode(alphaNode, hashKey.getObjectValue());
+ }
+
+ // end of the hashed alphas
+ handler.endHashedAlphaNodes(hashedFieldReader);
+ }
+ }
+
+ private void traverseSink(ObjectSink sink, NetworkHandler handler) {
+ if (sink instanceof AlphaNode) {
+ AlphaNode alphaNode = (AlphaNode) sink;
+
+ handler.startNonHashedAlphaNode(alphaNode);
+
+ traversePropagator(alphaNode.getSinkPropagator(), handler);
+
+ handler.endNonHashedAlphaNode(alphaNode);
+ } else if (sink instanceof BetaNode) {
+ BetaNode betaNode = (BetaNode) sink;
+
+ handler.startBetaNode(betaNode);
+ // todo traverse beta
+ handler.endBetaNode(betaNode);
+ } else if (sink instanceof LeftInputAdapterNode) {
+ LeftInputAdapterNode leftInputAdapterNode = (LeftInputAdapterNode) sink;
+
+ handler.startLeftInputAdapterNode(leftInputAdapterNode);
+ // todo traverse lia
+ handler.endLeftInputAdapterNode(leftInputAdapterNode);
+ }
+ }
+
+ private void traverseSink(LeftTupleSink sink, NetworkHandler handler) {
+ // todo traverse sink's propagator
+ }
+
+ /**
+ * Returns the first {@link org.drools.reteoo.AlphaNode} from the specified {@link ObjectHashMap}.
+ *
+ * @param hashedAlphaNodes map of hashed AlphaNodes
+ * @return first alpha from the specified map
+ * @throws IllegalArgumentException thrown if the map doesn't contain any alpha nodes
+ */
+ private AlphaNode getFirstAlphaNode(final ObjectHashMap hashedAlphaNodes) throws IllegalArgumentException {
+ AlphaNode firstAlphaNode;
+
+ final Iterator iter = hashedAlphaNodes.iterator();
+ final ObjectHashMap.ObjectEntry entry = (ObjectHashMap.ObjectEntry) iter.next();
+
+ if (entry != null) {
+ firstAlphaNode = (AlphaNode) entry.getValue();
+ } else {
+ throw new IllegalArgumentException("ObjectHashMap does not contain any hashed AlphaNodes!");
+ }
+
+ return firstAlphaNode;
+ }
+
+ /**
+ * Returns the {@link ClassFieldReader} for the hashed AlphaNode. The AlphaNode's constraint has to be a
+ * LiteralConstraint. This is the only type of hashed alpha currently supported.
+ *
+ * @param alphaNode hashed alpha to get reader for
+ * @return ClassFieldReader
+ * @throws IllegalArgumentException thrown if the AlphaNode's {@link org.drools.spi.AlphaNodeFieldConstraint} is not a
+ * {@link org.drools.rule.LiteralConstraint}.
+ */
+ private ClassFieldReader getClassFieldReaderForHashedAlpha(final AlphaNode alphaNode) throws IllegalArgumentException {
+ final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+ if (!(fieldConstraint instanceof LiteralConstraint)) {
+ throw new IllegalArgumentException("Only support LiteralConstraint hashed AlphaNodes, not " + fieldConstraint.getClass());
+ }
+ // we need to get the first alpha in the map to get the attribute name that be use for the prefix of the
+ // generated variable name
+ final LiteralConstraint literalConstraint = (LiteralConstraint) alphaNode.getConstraint();
+
+ return (ClassFieldReader) literalConstraint.getFieldExtractor();
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/SetNodeReferenceHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/SetNodeReferenceHandler.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/compiled/SetNodeReferenceHandler.java 2009-07-17 01:22:31 UTC (rev 28125)
@@ -0,0 +1,101 @@
+package org.drools.reteoo.compiled;
+
+import org.drools.common.NetworkNode;
+import org.drools.reteoo.*;
+
+/**
+ * This handler is used to create the member variable assignment statements section of a generated subclass of a
+ * {@link CompiledNetwork#setNetworkNodeReference(org.drools.common.NetworkNode)}.
+ * Currently we only need to create member variable assignments for the following types of nodes:
+ * <p/>
+ * <li>Non-hashed {@link AlphaNode}s</li>
+ * <li>{@link LeftInputAdapterNode}s</li>
+ * <li>{@link BetaNode}s</li>
+ *
+ * @author <a href="mailto:stampy88 at yahoo.com">dave sinclair</a>
+ */
+class SetNodeReferenceHandler extends AbstractCompilerHandler {
+
+ private static final String PARAM_TYPE = NetworkNode.class.getName();
+ private static final String PARAM_NAME = "node";
+ private static final String SET_NETWORK_NODE_REFERENCE_SIGNATURE = "protected void setNetworkNodeReference("
+ + PARAM_TYPE + " " + PARAM_NAME + "){";
+
+ private final StringBuilder builder;
+
+ SetNodeReferenceHandler(StringBuilder builder) {
+ this.builder = builder;
+ }
+
+ private String getVariableAssignmentStatement(Sink sink, String nodeVariableName) {
+ Class<?> variableType = getVariableType(sink);
+ String assignmentStatement;
+
+ // for non alphas, we just need to cast to the right variable type
+ assignmentStatement = getVariableName(sink) + " = (" + variableType.getName() + ")" + nodeVariableName + ";";
+
+ return assignmentStatement;
+ }
+
+ private String getVariableAssignmentStatement(AlphaNode alphaNode, String nodeVariableName) {
+ Class<?> variableType = getVariableType(alphaNode);
+ String assignmentStatement;
+
+ // we need the constraint for an alpha node assignment, so generate a cast, plus the method call to get
+ // the constraint
+ assignmentStatement = getVariableName(alphaNode) + " = (" + variableType.getName() + ") ((" + AlphaNode.class.getName() + ")" + nodeVariableName + ").getConstraint();";
+
+ return assignmentStatement;
+ }
+
+
+ @Override
+ public void startObjectTypeNode(ObjectTypeNode objectTypeNode) {
+ builder.append(SET_NETWORK_NODE_REFERENCE_SIGNATURE).append(NEWLINE);
+ // we are switch based on the parameter's node ID
+ builder.append("switch (").append(PARAM_NAME).append(".getId()) {").append(NEWLINE);
+ }
+
+ @Override
+ public void endObjectTypeNode(ObjectTypeNode objectTypeNode) {
+ // close the switch
+ builder.append("}").append(NEWLINE);
+ // and close the setNetworkNodeReference method
+ builder.append("}").append(NEWLINE);
+ }
+
+ @Override
+ public void startNonHashedAlphaNode(AlphaNode alphaNode) {
+ // case statement for the non-hashed alphas looks like the following
+ // case 24:
+ // variableConstraint24 = (VariableConstraint) ((AlphaNode) node).getConstraint();
+ // break;
+
+ builder.append("case ").append(alphaNode.getId()).append(": ").append(NEWLINE);
+ builder.append(getVariableAssignmentStatement(alphaNode, PARAM_NAME)).append(NEWLINE);
+ builder.append("break;").append(NEWLINE);
+ }
+
+ @Override
+ public void startBetaNode(BetaNode betaNode) {
+ // case statement for the betas looks like the following
+ // case 65:
+ // notNode65 = (NodeNode) node;
+ // break;
+
+ builder.append("case ").append(betaNode.getId()).append(": ").append(NEWLINE);
+ builder.append(getVariableAssignmentStatement(betaNode, PARAM_NAME)).append(NEWLINE);
+ builder.append("break;").append(NEWLINE);
+ }
+
+ @Override
+ public void startLeftInputAdapterNode(LeftInputAdapterNode leftInputAdapterNode) {
+ // case statement for the lias looks like the following
+ // case 5:
+ // leftInputAdapterNode5 = (LeftInputAdapterNode) node;
+ // break;
+ builder.append("case ").append(leftInputAdapterNode.getId()).append(": ").append(NEWLINE);
+ builder.append(getVariableAssignmentStatement(leftInputAdapterNode, PARAM_NAME)).append(NEWLINE);
+ builder.append("break;").append(NEWLINE);
+ }
+}
More information about the jboss-svn-commits
mailing list