[jboss-svn-commits] JBL Code SVN: r6259 - in labs/jbossrules/branches/3.0.x/drools-decisiontables/src: main/java/org/drools/decisiontable main/java/org/drools/decisiontable/model main/java/org/drools/decisiontable/parser test/java/org/drools/decisiontable test/java/org/drools/decisiontable/model test/java/org/drools/decisiontable/parser test/resources/data
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Sep 18 06:48:22 EDT 2006
Author: stevearoonie
Date: 2006-09-18 06:48:00 -0400 (Mon, 18 Sep 2006)
New Revision: 6259
Added:
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
Modified:
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/model/RuleRenderTest.java
labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java
Log:
JBRULES-483 - extract RuleSheetListener interface from default implementation and allow custom listeners to be used to parse spreadsheets. Added new custom listener for matrix style spreadsheets
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -23,6 +23,7 @@
import org.drools.decisiontable.model.DRLOutput;
import org.drools.decisiontable.model.Package;
import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.decisiontable.parser.DefaultRuleSheetListener;
import org.drools.decisiontable.parser.RuleSheetListener;
import org.drools.decisiontable.parser.xls.ExcelParser;
@@ -44,8 +45,28 @@
*/
public String compile(final InputStream xlsStream,
final InputType type) {
- final RuleSheetListener listener = getRuleSheetListener( xlsStream,
- type );
+ return compile( xlsStream,
+ type,
+ new DefaultRuleSheetListener() );
+ }
+
+ /**
+ * Generates DRL from the input stream containing the spreadsheet.
+ *
+ * @param xlsStream
+ * The stream to the spreadsheet. Uses the first worksheet found
+ * for the decision tables, ignores others.
+ * @param type
+ * The type of the file - InputType.CSV or InputType.XLS
+ * @param listener
+ *
+ * @return DRL xml, ready for use in drools.
+ */
+ public String compile(final InputStream xlsStream,
+ final InputType type,
+ final RuleSheetListener listener) {
+ final DecisionTableParser parser = type.createParser( listener );
+ parser.parseFile( xlsStream );
final Package rulePackage = listener.getRuleSet();
final DRLOutput out = new DRLOutput();
rulePackage.renderDRL( out );
@@ -67,7 +88,7 @@
final InputStream stream = this.getClass().getResourceAsStream( classPathResource );
try {
final String drl = compile( stream,
- inputType );
+ inputType );
return drl;
} finally {
closeStream( stream );
@@ -87,7 +108,7 @@
public String compile(final InputStream stream,
final String worksheetName) {
final RuleSheetListener listener = getRuleSheetListener( stream,
- worksheetName );
+ worksheetName );
final Package rulePackage = listener.getRuleSet();
final DRLOutput out = new DRLOutput();
rulePackage.renderDRL( out );
@@ -95,17 +116,8 @@
}
private RuleSheetListener getRuleSheetListener(final InputStream stream,
- final InputType type) {
- final RuleSheetListener listener = new RuleSheetListener();
-
- final DecisionTableParser parser = type.createParser( listener );
- parser.parseFile( stream );
- return listener;
- }
-
- private RuleSheetListener getRuleSheetListener(final InputStream stream,
final String worksheetName) {
- final RuleSheetListener listener = new RuleSheetListener();
+ final RuleSheetListener listener = new DefaultRuleSheetListener();
final Map listeners = new HashMap();
listeners.put( worksheetName,
listener );
@@ -122,4 +134,4 @@
}
}
-}
\ No newline at end of file
+}
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -17,13 +17,10 @@
*/
import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import org.drools.decisiontable.parser.SourceBuilder;
-
/**
* @author <a href="mailto:michael.neale at gmail.com"> Michael Neale </a>
*
@@ -52,12 +49,15 @@
private String _activationGroup; // RIK: New variable to the Rule class (Set the
// activation-group parameter of the rule tag)
+ private String _agendaGroup; // SJW: New variable to the Rule class (Set the
+ // agenda-group parameter of the rule tag
+
private List _lhs;
private List _rhs;
private int _spreadsheetRow;
-
+
/**
* Create a new rule. Note that the rule name should be post-fixed with the row number,
* as one way of providing tracability for errors back to the originating spreadsheet.
@@ -78,7 +78,6 @@
this._rhs = new LinkedList();
this._spreadsheetRow = spreadsheetRow;
}
-
public void addCondition(final Condition con) {
this._lhs.add( con );
@@ -102,6 +101,9 @@
if ( this._activationGroup != null ) {
out.writeLine( "\tactivation-group \"" + this._activationGroup + "\"" );
}
+ if ( this._agendaGroup != null ) {
+ out.writeLine( "\tagenda-group " + this._agendaGroup );
+ }
if ( this._noLoop != null ) {
out.writeLine( "\tno-loop " + this._noLoop );
}
@@ -225,7 +227,7 @@
return this._duration.getSnippet();
}
- public void setActivationrGroup(final String value) // Set the duration of the rule
+ public void setActivationGroup(final String value) // Set the duration of the rule
{
this._activationGroup = value;
}
@@ -234,12 +236,20 @@
return this._activationGroup;
}
+ public String getAgendaGroup() {
+ return _agendaGroup;
+ }
+
+ public void setAgendaGroup(String group) // Set the agenda-group of the rule
+ {
+ _agendaGroup = group;
+ }
+
public void setNoLoop(final String value) // Set the no-loop attribute of the rule
{
this._noLoop = value;
}
-
/**
* @return The row in the spreadsheet this represents.
* This can be handy when mapping a line error from Parser back to the rule row.
@@ -250,4 +260,4 @@
return this._spreadsheetRow;
}
-}
\ No newline at end of file
+}
Added: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -0,0 +1,574 @@
+package org.drools.decisiontable.parser;
+
+/*
+ * Copyright 2005 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.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.drools.decisiontable.model.Condition;
+import org.drools.decisiontable.model.Consequence;
+import org.drools.decisiontable.model.Duration;
+import org.drools.decisiontable.model.Global;
+import org.drools.decisiontable.model.Import;
+import org.drools.decisiontable.model.Package;
+import org.drools.decisiontable.model.Rule;
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener;
+
+/**
+ * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a><a
+ * href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ *
+ * Define a ruleset spreadsheet which contains one or more decision tables.
+ *
+ * Stay calm, deep breaths... this is a little bit scary, its where it all
+ * happens.
+ *
+ * A table is identifed by a cell beginning with the text "RuleTable". The first
+ * row after the table identifier defines the column type: either a condition
+ * ("C") or consequence ("A" for action), and so on.
+ *
+ * The second row contains ObjectType declarations (optionally, or can be left blank).
+ * If cells are merged, then all snippets below the merged bit will become part of
+ * the same column as seperate constraints.
+ *
+ * The third row identifies the java code block associated with the condition
+ * or consequence. This code block will include a parameter marker for the
+ * attribute defined by that column.
+ *
+ * The third row is a label for the attribute associated with that column.
+ *
+ * All subsequent rows identify rules with the set.
+ */
+public class DefaultRuleSheetListener
+ implements
+ RuleSheetListener {
+
+ //keywords
+ public static final String FUNCTIONS_TAG = "Functions";
+ public static final String IMPORT_TAG = "Import";
+ public static final String SEQUENTIAL_FLAG = "Sequential";
+ public static final String VARIABLES_TAG = "Variables";
+ public static final String RULE_TABLE_TAG = "RuleTable";
+ public static final String RULESET_TAG = "RuleSet";
+ private static final int ACTION_ROW = 1;
+ private static final int OBJECT_TYPE_ROW = 2;
+ private static final int CODE_ROW = 3;
+ private static final int LABEL_ROW = 4;
+
+ //state machine variables for this parser
+ private boolean _isInRuleTable = false;
+ private int _ruleRow;
+ private int _ruleStartColumn;
+ private int _ruleStartRow;
+ private Rule _currentRule;
+ private String _currentRulePrefix;
+ private boolean _currentSequentialFlag = false; // indicates that we are in sequential mode
+
+ //accumulated output
+ private Map _actions;
+ private final HashMap _cellComments = new HashMap();
+ private final List _ruleList = new LinkedList();
+
+ //need to keep an ordered list of this to make conditions appear in the right order
+ private List sourceBuilders = new ArrayList();
+
+ private final PropertiesSheetListener _propertiesListner = new PropertiesSheetListener();
+
+ /* (non-Javadoc)
+ * @see org.drools.decisiontable.parser.RuleSheetListener#getProperties()
+ */
+ public Properties getProperties() {
+ return this._propertiesListner.getProperties();
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.decisiontable.parser.RuleSheetListener#getRuleSet()
+ */
+ public Package getRuleSet() {
+ if ( this._ruleList.isEmpty() ) {
+ throw new DecisionTableParseException( "No RuleTable's were found in spreadsheet." );
+ }
+ final Package ruleset = buildRuleSet();
+ return ruleset;
+ }
+
+ /**
+ * Add a new rule to the current list of rules
+ * @param rule
+ */
+ protected void addRule(final Rule newRule) {
+ this._ruleList.add( newRule );
+ }
+
+ private Package buildRuleSet() {
+ final String rulesetName = getProperties().getProperty( DefaultRuleSheetListener.RULESET_TAG,
+ "rule_table" );
+ final Package ruleset = new Package( rulesetName );
+ for ( final Iterator it = this._ruleList.iterator(); it.hasNext(); ) {
+ ruleset.addRule( (Rule) it.next() );
+ }
+ final List importList = RuleSheetParserUtil.getImportList( getProperties().getProperty( DefaultRuleSheetListener.IMPORT_TAG ) );
+ for ( final Iterator it = importList.iterator(); it.hasNext(); ) {
+ ruleset.addImport( (Import) it.next() );
+ }
+ final List variableList = RuleSheetParserUtil.getVariableList( getProperties().getProperty( DefaultRuleSheetListener.VARIABLES_TAG ) ); // Set the list of variables to
+ // be added to the
+ // application-data tags
+ for ( final Iterator it = variableList.iterator(); it.hasNext(); ) {
+ ruleset.addVariable( (Global) it.next() );
+ }
+
+ final String functions = getProperties().getProperty( DefaultRuleSheetListener.FUNCTIONS_TAG );
+ ruleset.addFunctions( functions );
+ return ruleset;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see my.hssf.util.SheetListener#startSheet(java.lang.String)
+ */
+ public void startSheet(final String name) {
+ // nothing to see here... move along..
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see my.hssf.util.SheetListener#finishSheet()
+ */
+ public void finishSheet() {
+ this._propertiesListner.finishSheet();
+ finishRuleTable();
+ flushRule();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see my.hssf.util.SheetListener#newRow()
+ */
+ public void newRow(final int rowNumber,
+ final int columns) {
+ if (_currentRule != null)
+ flushRule();
+ // nothing to see here... these aren't the droids your looking for..
+ // move along...
+ }
+
+ /**
+ * This makes sure that the rules have all their components added.
+ * As when there are merged/spanned cells, they may be left out.
+ */
+ private void flushRule() {
+ for ( Iterator iter = sourceBuilders.iterator(); iter.hasNext(); ) {
+ SourceBuilder src = (SourceBuilder) iter.next();
+ if (src.hasValues()) {
+ if (src instanceof LhsBuilder) {
+ Condition con = new Condition();
+ con.setSnippet( src.getResult() );
+ _currentRule.addCondition( con );
+ } else if (src instanceof RhsBuilder ) {
+ Consequence con = new Consequence();
+ con.setSnippet( src.getResult() );
+ _currentRule.addConsequence( con );
+ }
+ src.clearValues();
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see my.hssf.util.SheetListener#newCell(int, int, java.lang.String)
+ */
+ public void newCell(final int row,
+ final int column,
+ final String value,
+ int mergedColStart) {
+ if ( isCellValueEmpty( value ) ) {
+ return;
+ }
+ if (_isInRuleTable && row == this._ruleStartRow) {
+ return;
+ }
+ if ( this._isInRuleTable ) {
+ processRuleCell( row,
+ column,
+ value,
+ mergedColStart);
+ } else {
+ processNonRuleCell( row,
+ column,
+ value );
+ }
+ }
+
+ /**
+ * This gets called each time a "new" rule table is found.
+ */
+ private void initRuleTable(final int row,
+ final int column,
+ final String value) {
+ preInitRuleTable(row, column, value);
+ this._isInRuleTable = true;
+ this._actions = new HashMap();
+ this.sourceBuilders = new ArrayList();
+ this._ruleStartColumn = column;
+ this._ruleStartRow = row;
+ this._ruleRow = row + DefaultRuleSheetListener.LABEL_ROW + 1;
+
+ // setup stuff for the rules to come.. (the order of these steps are
+ // important !)
+ this._currentRulePrefix = RuleSheetParserUtil.getRuleName( value );
+ this._currentSequentialFlag = getSequentialFlag();
+
+ this._currentRule = createNewRuleForRow( this._ruleRow );
+
+ this._ruleList.add( this._currentRule );
+ postInitRuleTable(row, column, value);
+
+ }
+
+ /**
+ * Called before rule table initialisation. Subclasses may
+ * override this method to do additional processing.
+ */
+ protected void preInitRuleTable(int row,
+ int column,
+ String value) {
+ }
+
+ protected Rule getCurrentRule() {
+ return _currentRule;
+ }
+
+ /**
+ * Called after rule table initialisation. Subclasses may
+ * override this method to do additional processing.
+ */
+ protected void postInitRuleTable(int row,
+ int column,
+ String value) {
+ }
+
+ private boolean getSequentialFlag() {
+ final String seqFlag = getProperties().getProperty( DefaultRuleSheetListener.SEQUENTIAL_FLAG );
+ return RuleSheetParserUtil.isStringMeaningTrue( seqFlag );
+ }
+
+ private void finishRuleTable() {
+ if ( this._isInRuleTable ) {
+ this._currentSequentialFlag = false;
+ this._isInRuleTable = false;
+
+ }
+ }
+
+ private void processNonRuleCell(final int row,
+ final int column,
+ final String value) {
+ if ( value.startsWith( DefaultRuleSheetListener.RULE_TABLE_TAG ) ) {
+ initRuleTable( row,
+ column,
+ value );
+ } else {
+ this._propertiesListner.newCell( row,
+ column,
+ value, SheetListener.NON_MERGED);
+ }
+ }
+
+ private void processRuleCell(final int row,
+ final int column,
+ final String value,
+ final int mergedColStart) {
+ if ( value.startsWith( DefaultRuleSheetListener.RULE_TABLE_TAG ) ) {
+ finishRuleTable();
+ initRuleTable( row,
+ column,
+ value );
+ return;
+ }
+
+ // Ignore any comments cells preceeding the first rule table column
+ if ( column < this._ruleStartColumn ) {
+ return;
+ }
+
+ // Ignore any further cells from the rule def row
+ if ( row == this._ruleStartRow ) {
+ return;
+ }
+
+ switch ( row - this._ruleStartRow ) {
+ case ACTION_ROW :
+ ActionType.addNewActionType( this._actions,
+ value,
+ column,
+ row );
+ break;
+ case OBJECT_TYPE_ROW :
+ objectTypeRow( row,
+ column,
+ value,
+ mergedColStart);
+ break;
+ case CODE_ROW :
+ codeRow( row,
+ column,
+ value );
+ break;
+ case LABEL_ROW :
+ labelRow( row,
+ column,
+ value );
+ break;
+ default :
+ nextDataCell( row,
+ column,
+ value );
+ break;
+ }
+ }
+
+ /**
+ * This is for handling a row where an object declaration may appear,
+ * this is the row immediately above the snippets.
+ * It may be blank, but there has to be a row here.
+ *
+ * Merged cells have "special meaning" which is why this is so freaking hard.
+ * A future refactor may be to move away from an "event" based listener.
+ */
+ private void objectTypeRow(final int row,
+ final int column,
+ final String value,
+ final int mergedColStart) {
+ if (value.indexOf( "$param" ) > -1 || value.indexOf( "$1" ) > -1) {
+ throw new DecisionTableParseException("It looks like you have snippets in the row that is " +
+ "meant for column declarations." +
+ " Please insert an additional row before the snippets." +
+ " Row number: " + (row + 1));
+ }
+ ActionType action = getActionForColumn( row, column );
+ if (mergedColStart == SheetListener.NON_MERGED) {
+ if (action.type == ActionType.CONDITION) {
+ SourceBuilder src = new LhsBuilder(value);
+ action.setSourceBuilder(src);
+ this.sourceBuilders.add(src);
+
+ } else if (action.type == ActionType.ACTION) {
+ SourceBuilder src = new RhsBuilder(value);
+ action.setSourceBuilder(src);
+ this.sourceBuilders.add(src);
+ }
+ } else {
+ if (column == mergedColStart) {
+ if (action.type == ActionType.CONDITION) {
+ action.setSourceBuilder(new LhsBuilder(value));
+ this.sourceBuilders.add( action.getSourceBuilder() );
+ } else if (action.type == ActionType.ACTION) {
+ action.setSourceBuilder(new RhsBuilder(value));
+ this.sourceBuilders.add( action.getSourceBuilder() );
+ }
+ } else {
+ ActionType startOfMergeAction = getActionForColumn( row, mergedColStart );
+ action.setSourceBuilder( startOfMergeAction.getSourceBuilder() );
+ }
+
+ }
+ }
+
+ private void codeRow(final int row,
+ final int column,
+ final String value) {
+ final ActionType actionType = getActionForColumn( row, column );
+ if (actionType.getSourceBuilder() == null) {
+ if (actionType.type == ActionType.CONDITION) {
+ actionType.setSourceBuilder( new LhsBuilder(null) );
+ this.sourceBuilders.add( actionType.getSourceBuilder() );
+ } else if (actionType.type == ActionType.ACTION) {
+ actionType.setSourceBuilder( new RhsBuilder(null) );
+ this.sourceBuilders.add( actionType.getSourceBuilder() );
+ }
+ }
+ if ( value.trim().equals( "" ) && (actionType.type == ActionType.ACTION || actionType.type == ActionType.CONDITION) ) {
+ throw new DecisionTableParseException( "Code description - row:" + (row + 1) + " cell number:" + (column + 1) + " - does not contain any code specification. It should !" );
+ }
+
+ actionType.addTemplate(column, value);
+ }
+
+ private void labelRow(final int row,
+ final int column,
+ final String value) {
+ final ActionType actionType = getActionForColumn( row,
+ column );
+
+ if ( !value.trim().equals( "" ) && (actionType.type == ActionType.ACTION || actionType.type == ActionType.CONDITION) ) {
+ this._cellComments.put( new Integer( column ),
+ value );
+ } else {
+ this._cellComments.put( new Integer( column ),
+ "From column: " + Rule.convertColNumToColName( column ) );
+ }
+ }
+
+ private ActionType getActionForColumn(final int row,
+ final int column) {
+ final ActionType actionType = (ActionType) this._actions.get( new Integer( column ) );
+
+ if ( actionType == null ) {
+ throw new DecisionTableParseException( "Code description - row number:" + (row + 1) + " cell number:" + (column + 1) + " - does not have an 'ACTION' or 'CONDITION' column header." );
+ }
+
+ return actionType;
+ }
+
+ private void nextDataCell(final int row,
+ final int column,
+ final String value) {
+ final ActionType actionType = getActionForColumn( row,
+ column );
+
+ if ( row - this._ruleRow > 1 ) {
+ // Encountered a row gap from the last rule.
+ // This is not part of the ruleset.
+ finishRuleTable();
+ processNonRuleCell( row,
+ column,
+ value );
+ return;
+ }
+
+ if ( row > this._ruleRow ) {
+ // In a new row/rule
+ this._currentRule = createNewRuleForRow( row );
+
+ this._ruleList.add( this._currentRule );
+ this._ruleRow++;
+ }
+
+ //if the rule set is not sequential and the actionType type is PRIORITY then set the current Rule's salience paramenter with the value got from the cell
+ if ( actionType.type == ActionType.PRIORITY && !this._currentSequentialFlag ) {
+ this._currentRule.setSalience( new Integer( value ) );
+ } else if ( actionType.type == ActionType.NAME ) // if the actionType
+ // type is PRIORITY then
+ // set the current
+ // Rule's name
+ // paramenter with the
+ // value got from the
+ // cell
+ {
+ this._currentRule.setName( value );
+ } else if ( actionType.type == ActionType.DESCRIPTION ) // if the
+ // actionType
+ // type is
+ // DESCRIPTION
+ // then set the
+ // current
+ // Rule's
+ // description
+ // paramenter
+ // with the
+ // value got
+ // from the cell
+ {
+ this._currentRule.setDescription( value );
+ } else if ( actionType.type == ActionType.ACTIVATIONGROUP ) // if the actionType
+ // type is NOLOOP
+ // then set the
+ // current Rule's
+ // no-loop
+ // paramenter with
+ // the value got
+ // from the cell
+ {
+ this._currentRule.setActivationGroup( value );
+ } else if ( actionType.type == ActionType.NOLOOP ) // if the actionType
+ // type is NOLOOP
+ // then set the
+ // current Rule's
+ // no-loop
+ // paramenter with
+ // the value got
+ // from the cell
+ {
+ this._currentRule.setNoLoop( value );
+ } else if ( actionType.type == ActionType.DURATION ) // if the actionType
+ // type is DURATION
+ // then creates a
+ // new duration tag
+ // with the value
+ // got from the cell
+ {
+ createDuration( column,
+ value,
+ actionType );
+ } else if ( actionType.type == ActionType.CONDITION || actionType.type == ActionType.ACTION ) {
+ actionType.addCellValue( column, value );
+ }
+
+ }
+
+ private Rule createNewRuleForRow(final int row) {
+
+
+ Integer salience = null;
+ if ( this._currentSequentialFlag ) {
+ salience = new Integer( Rule.calcSalience( row ) );
+ }
+ final int spreadsheetRow = row + 1;
+ final String name = this._currentRulePrefix + "_" + spreadsheetRow;
+ final Rule rule = new Rule( name,
+ salience,
+ spreadsheetRow );
+ rule.setComment( "From row number: " + (spreadsheetRow) );
+
+ return rule;
+
+ }
+
+
+ // 08 - 16 - 2005 RIK: This function creates a new DURATION
+ private void createDuration(final int column,
+ final String value,
+ final ActionType actionType) {
+
+ final Duration dur = new Duration();
+ dur.setSnippet( value );
+ dur.setComment( cellComment( column ) );
+ this._currentRule.setDuration( dur );
+ }
+
+
+ private boolean isCellValueEmpty(final String value) {
+ return value == null || "".equals( value.trim() );
+ }
+
+ private String cellComment(final int column) {
+ return "From column: " + Rule.convertColNumToColName( column );
+ }
+
+}
Added: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -0,0 +1,200 @@
+package org.drools.decisiontable.parser;
+
+/*
+ * Copyright 2005 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.drools.decisiontable.model.Condition;
+import org.drools.decisiontable.model.Consequence;
+import org.drools.decisiontable.model.Rule;
+import org.drools.decisiontable.model.SnippetBuilder;
+import org.drools.decisiontable.parser.DefaultRuleSheetListener;
+
+/**
+ * @author <a href="mailto:stevearoonie at gmail.com"> Steven Williams </a><a
+ * href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ *
+ * Define a ruleset spreadsheet which contains a matrix style decision tables.
+ *
+ * This is an example of a custom RuleSheetListener. It differs from the standard
+ * decision table in the following ways:
+ * - AgendaGroup property so that all rules fall within the same agenda-group
+ * - Precondition property which specifies a condition that is always included
+ * if a rule is being generated
+ * - Action property. Each cell within the decision table causes this action
+ * to be triggered
+ * - HorizontalCondition property. Each column header in the matrix
+ * applies this condition
+ * - VerticalCondition property. Each row header in the matrix applies this
+ * condition
+ *
+ * A table is identifed by a cell beginning with the text "RuleTable".
+ * The cells after RuleTable in the same row identify the Horizontal Conditions.
+ * The cells after RuleTable in the same column identify the Vertical Conditions.
+ * The cells with the matrix identify the actions.
+ * Wherever an action cell exists for a Vertical/Horizontal condition intersection
+ * the following rule is created:
+ * rule "rule_row_col"
+ * agenda-group AgendaGroup
+ * when
+ * Precondition
+ * VerticalCondition
+ * HorizontalCondition
+ * then
+ * Action
+ * end
+ */
+public class RuleMatrixSheetListener extends DefaultRuleSheetListener {
+
+ //keywords
+ public static final String AGENDAGROUP_TAG = "AgendaGroup";
+ public static final String PRECONDITION_TAG = "Precondition";
+ public static final String ACTION_TAG = "Action";
+ public static final String HORIZONTALCONDITION_TAG = "HorizontalCondition";
+ public static final String VERTICALCONDITION_TAG = "VerticalCondition";
+
+ //state machine variables for this parser
+ private int ruleTableRow;
+ private int ruleTableColumn;
+ private String _currentAgendaGroup;
+ private Condition _currentPrecondition;
+ private String _action;
+ private String _horizontalCondition;
+ private String _verticalCondition;
+ private List _horizontalConditions = new ArrayList();
+ private Condition _currentVerticalCondition;
+ private boolean isInRuleTable;
+ private Rule firstRule;
+
+ public void newCell(final int row,
+ final int column,
+ final String value,
+ final int mergedColStart) {
+ // if we aren't in the rule table just use the default handling
+ // (add a property)
+ if ( !isInRuleTable ) {
+ super.newCell( row,
+ column,
+ value,
+ mergedColStart );
+ return;
+ }
+ // ignore empty cells
+ if ( StringUtils.isEmpty( value ) ) {
+ return;
+ }
+
+ //Horizontal header column
+ //Create a new condition using HorizontalCondition as the template
+ //and save it for later use
+ if ( row == (ruleTableRow) && column > ruleTableColumn ) {
+ _horizontalConditions.add( createCondition( value,
+ _horizontalCondition ) );
+ }
+ //Vertical header column
+ //Create a new condition using VerticalCondition as the template
+ //and set it as the current condition
+ else if ( row > (ruleTableRow) && column == ruleTableColumn ) {
+ _currentVerticalCondition = createCondition( value,
+ _verticalCondition );
+ }
+ //Intersection column
+ //Create a new Consequence
+ else if ( row > (ruleTableRow) && column > ruleTableColumn ) {
+ createRule( row,
+ column,
+ value );
+ }
+ }
+
+ private void createRule(final int row,
+ final int column,
+ final String value) {
+ Rule rule = firstRule;
+ if ( rule == null ) {
+ rule = new Rule( "rule_" + row + "_" + column,
+ null,
+ row );
+ addRule( rule );
+ } else {
+ firstRule = null;
+ rule.setName( "rule_" + row + "_" + column );
+ }
+ rule.setAgendaGroup( this._currentAgendaGroup );
+ rule.addCondition( this._currentPrecondition );
+ rule.addCondition( _currentVerticalCondition );
+ rule.addCondition( (Condition) _horizontalConditions.get( column - (ruleTableColumn + 1) ) );
+ rule.addConsequence( createConsequence( value ) );
+ }
+
+ private Consequence createConsequence(final String value) {
+ final SnippetBuilder snip = new SnippetBuilder( _action );
+ final String result = snip.build( value );
+ final Consequence consequence = new Consequence();
+ consequence.setSnippet( result );
+ return consequence;
+ }
+
+ private Condition createCondition(final String value,
+ final String conditionTemplate) {
+ SnippetBuilder snip = new SnippetBuilder( conditionTemplate );
+ String result = snip.build( value );
+ Condition condition = new Condition();
+ condition.setSnippet( result );
+ return condition;
+ }
+
+ public void newRow(int rowNumber,
+ int columns) {
+ // nothing to do here
+ }
+
+ public void finishSheet() {
+ // nothing to do here
+ }
+
+ protected void postInitRuleTable(int row,
+ int column,
+ String value) {
+ this.firstRule = getCurrentRule();
+ }
+
+ /**
+ * This gets called each time a "new" rule table is found.
+ */
+ protected void preInitRuleTable(final int row,
+ final int column,
+ final String value) {
+ this.ruleTableColumn = column;
+ this.ruleTableRow = row;
+ this.isInRuleTable = true;
+ this._currentAgendaGroup = getProperties().getProperty( AGENDAGROUP_TAG,
+ null );
+ this._action = getProperties().getProperty( ACTION_TAG );
+ this._horizontalCondition = getProperties().getProperty( HORIZONTALCONDITION_TAG );
+ this._verticalCondition = getProperties().getProperty( VERTICALCONDITION_TAG );
+ String precondition = getProperties().getProperty( PRECONDITION_TAG,
+ null );
+ if ( precondition != null ) {
+ this._currentPrecondition = new Condition();
+ this._currentPrecondition.setSnippet( precondition );
+ }
+ }
+
+}
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -1,543 +1,24 @@
package org.drools.decisiontable.parser;
-/*
- * Copyright 2005 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.
- */
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
import java.util.Properties;
-import org.drools.decisiontable.model.Condition;
-import org.drools.decisiontable.model.Consequence;
-import org.drools.decisiontable.model.Duration;
-import org.drools.decisiontable.model.Global;
-import org.drools.decisiontable.model.Import;
import org.drools.decisiontable.model.Package;
-import org.drools.decisiontable.model.Rule;
-import org.drools.decisiontable.parser.xls.PropertiesSheetListener;
/**
- * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a><a
- * href="mailto:michael.neale at gmail.com"> Michael Neale </a>
- *
- * Define a ruleset spreadsheet which contains one or more decision tables.
- *
- * Stay calm, deep breaths... this is a little bit scary, its where it all
- * happens.
- *
- * A table is identifed by a cell beginning with the text "RuleTable". The first
- * row after the table identifier defines the column type: either a condition
- * ("C") or consequence ("A" for action), and so on.
- *
- * The second row contains ObjectType declarations (optionally, or can be left blank).
- * If cells are merged, then all snippets below the merged bit will become part of
- * the same column as seperate constraints.
- *
- * The third row identifies the java code block associated with the condition
- * or consequence. This code block will include a parameter marker for the
- * attribute defined by that column.
- *
- * The third row is a label for the attribute associated with that column.
- *
- * All subsequent rows identify rules with the set.
+ * Listener used to parse decision table spreadsheets
*/
-public class RuleSheetListener
- implements
+public interface RuleSheetListener
+ extends
SheetListener {
- //keywords
- public static final String FUNCTIONS_TAG = "Functions";
- public static final String IMPORT_TAG = "Import";
- public static final String SEQUENTIAL_FLAG = "Sequential";
- public static final String VARIABLES_TAG = "Variables";
- public static final String RULE_TABLE_TAG = "RuleTable";
- public static final String RULESET_TAG = "RuleSet";
- private static final int ACTION_ROW = 1;
- private static final int OBJECT_TYPE_ROW = 2;
- private static final int CODE_ROW = 3;
- private static final int LABEL_ROW = 4;
-
- //state machine variables for this parser
- private boolean _isInRuleTable = false;
- private int _ruleRow;
- private int _ruleStartColumn;
- private int _ruleStartRow;
- private Rule _currentRule;
- private String _currentRulePrefix;
- private boolean _currentSequentialFlag = false; // indicates that we are in sequential mode
-
- //accumulated output
- private Map _actions;
- private final HashMap _cellComments = new HashMap();
- private final List _ruleList = new LinkedList();
-
- //need to keep an ordered list of this to make conditions appear in the right order
- private List sourceBuilders = new ArrayList();
-
- private final PropertiesSheetListener _propertiesListner = new PropertiesSheetListener();
-
/**
* Return the rule sheet properties
*/
- public Properties getProperties() {
- return this._propertiesListner.getProperties();
- }
+ public abstract Properties getProperties();
/**
* Build the final ruleset as parsed.
*/
- public Package getRuleSet() {
- if ( this._ruleList.isEmpty() ) {
- throw new DecisionTableParseException( "No RuleTable's were found in spreadsheet." );
- }
- final Package ruleset = buildRuleSet();
- return ruleset;
- }
+ public abstract Package getRuleSet();
- private Package buildRuleSet() {
- final String rulesetName = getProperties().getProperty( RuleSheetListener.RULESET_TAG,
- "rule_table" );
- final Package ruleset = new Package( rulesetName );
- for ( final Iterator it = this._ruleList.iterator(); it.hasNext(); ) {
- ruleset.addRule( (Rule) it.next() );
- }
- final List importList = RuleSheetParserUtil.getImportList( getProperties().getProperty( RuleSheetListener.IMPORT_TAG ) );
- for ( final Iterator it = importList.iterator(); it.hasNext(); ) {
- ruleset.addImport( (Import) it.next() );
- }
- final List variableList = RuleSheetParserUtil.getVariableList( getProperties().getProperty( RuleSheetListener.VARIABLES_TAG ) ); // Set the list of variables to
- // be added to the
- // application-data tags
- for ( final Iterator it = variableList.iterator(); it.hasNext(); ) {
- ruleset.addVariable( (Global) it.next() );
- }
-
- final String functions = getProperties().getProperty( RuleSheetListener.FUNCTIONS_TAG );
- ruleset.addFunctions( functions );
- return ruleset;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see my.hssf.util.SheetListener#startSheet(java.lang.String)
- */
- public void startSheet(final String name) {
- // nothing to see here... move along..
- }
-
- /*
- * (non-Javadoc)
- *
- * @see my.hssf.util.SheetListener#finishSheet()
- */
- public void finishSheet() {
- this._propertiesListner.finishSheet();
- finishRuleTable();
- flushRule();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see my.hssf.util.SheetListener#newRow()
- */
- public void newRow(final int rowNumber,
- final int columns) {
- if (_currentRule != null)
- flushRule();
- // nothing to see here... these aren't the droids your looking for..
- // move along...
- }
-
- /**
- * This makes sure that the rules have all their components added.
- * As when there are merged/spanned cells, they may be left out.
- */
- private void flushRule() {
- for ( Iterator iter = sourceBuilders.iterator(); iter.hasNext(); ) {
- SourceBuilder src = (SourceBuilder) iter.next();
- if (src.hasValues()) {
- if (src instanceof LhsBuilder) {
- Condition con = new Condition();
- con.setSnippet( src.getResult() );
- _currentRule.addCondition( con );
- } else if (src instanceof RhsBuilder ) {
- Consequence con = new Consequence();
- con.setSnippet( src.getResult() );
- _currentRule.addConsequence( con );
- }
- src.clearValues();
- }
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see my.hssf.util.SheetListener#newCell(int, int, java.lang.String)
- */
- public void newCell(final int row,
- final int column,
- final String value,
- int mergedColStart) {
- if ( isCellValueEmpty( value ) ) {
- return;
- }
- if (_isInRuleTable && row == this._ruleStartRow) {
- return;
- }
- if ( this._isInRuleTable ) {
- processRuleCell( row,
- column,
- value,
- mergedColStart);
- } else {
- processNonRuleCell( row,
- column,
- value );
- }
- }
-
- /**
- * This gets called each time a "new" rule table is found.
- */
- private void initRuleTable(final int row,
- final int column,
- final String value) {
-
- this._isInRuleTable = true;
- this._actions = new HashMap();
- this.sourceBuilders = new ArrayList();
- this._ruleStartColumn = column;
- this._ruleStartRow = row;
- this._ruleRow = row + RuleSheetListener.LABEL_ROW + 1;
-
- // setup stuff for the rules to come.. (the order of these steps are
- // important !)
- this._currentRulePrefix = RuleSheetParserUtil.getRuleName( value );
- this._currentSequentialFlag = getSequentialFlag();
-
- this._currentRule = createNewRuleForRow( this._ruleRow );
-
- this._ruleList.add( this._currentRule );
-
- }
-
- private boolean getSequentialFlag() {
- final String seqFlag = getProperties().getProperty( RuleSheetListener.SEQUENTIAL_FLAG );
- return RuleSheetParserUtil.isStringMeaningTrue( seqFlag );
- }
-
- private void finishRuleTable() {
- if ( this._isInRuleTable ) {
- this._currentSequentialFlag = false;
- this._isInRuleTable = false;
-
- }
- }
-
- private void processNonRuleCell(final int row,
- final int column,
- final String value) {
- if ( value.startsWith( RuleSheetListener.RULE_TABLE_TAG ) ) {
- initRuleTable( row,
- column,
- value );
- } else {
- this._propertiesListner.newCell( row,
- column,
- value, SheetListener.NON_MERGED);
- }
- }
-
- private void processRuleCell(final int row,
- final int column,
- final String value,
- final int mergedColStart) {
- if ( value.startsWith( RuleSheetListener.RULE_TABLE_TAG ) ) {
- finishRuleTable();
- initRuleTable( row,
- column,
- value );
- return;
- }
-
- // Ignore any comments cells preceeding the first rule table column
- if ( column < this._ruleStartColumn ) {
- return;
- }
-
- // Ignore any further cells from the rule def row
- if ( row == this._ruleStartRow ) {
- return;
- }
-
- switch ( row - this._ruleStartRow ) {
- case ACTION_ROW :
- ActionType.addNewActionType( this._actions,
- value,
- column,
- row );
- break;
- case OBJECT_TYPE_ROW :
- objectTypeRow( row,
- column,
- value,
- mergedColStart);
- break;
- case CODE_ROW :
- codeRow( row,
- column,
- value );
- break;
- case LABEL_ROW :
- labelRow( row,
- column,
- value );
- break;
- default :
- nextDataCell( row,
- column,
- value );
- break;
- }
- }
-
- /**
- * This is for handling a row where an object declaration may appear,
- * this is the row immediately above the snippets.
- * It may be blank, but there has to be a row here.
- *
- * Merged cells have "special meaning" which is why this is so freaking hard.
- * A future refactor may be to move away from an "event" based listener.
- */
- private void objectTypeRow(final int row,
- final int column,
- final String value,
- final int mergedColStart) {
- if (value.indexOf( "$param" ) > -1 || value.indexOf( "$1" ) > -1) {
- throw new DecisionTableParseException("It looks like you have snippets in the row that is " +
- "meant for column declarations." +
- " Please insert an additional row before the snippets." +
- " Row number: " + (row + 1));
- }
- ActionType action = getActionForColumn( row, column );
- if (mergedColStart == SheetListener.NON_MERGED) {
- if (action.type == ActionType.CONDITION) {
- SourceBuilder src = new LhsBuilder(value);
- action.setSourceBuilder(src);
- this.sourceBuilders.add(src);
-
- } else if (action.type == ActionType.ACTION) {
- SourceBuilder src = new RhsBuilder(value);
- action.setSourceBuilder(src);
- this.sourceBuilders.add(src);
- }
- } else {
- if (column == mergedColStart) {
- if (action.type == ActionType.CONDITION) {
- action.setSourceBuilder(new LhsBuilder(value));
- this.sourceBuilders.add( action.getSourceBuilder() );
- } else if (action.type == ActionType.ACTION) {
- action.setSourceBuilder(new RhsBuilder(value));
- this.sourceBuilders.add( action.getSourceBuilder() );
- }
- } else {
- ActionType startOfMergeAction = getActionForColumn( row, mergedColStart );
- action.setSourceBuilder( startOfMergeAction.getSourceBuilder() );
- }
-
- }
- }
-
- private void codeRow(final int row,
- final int column,
- final String value) {
- final ActionType actionType = getActionForColumn( row, column );
- if (actionType.getSourceBuilder() == null) {
- if (actionType.type == ActionType.CONDITION) {
- actionType.setSourceBuilder( new LhsBuilder(null) );
- this.sourceBuilders.add( actionType.getSourceBuilder() );
- } else if (actionType.type == ActionType.ACTION) {
- actionType.setSourceBuilder( new RhsBuilder(null) );
- this.sourceBuilders.add( actionType.getSourceBuilder() );
- }
- }
- if ( value.trim().equals( "" ) && (actionType.type == ActionType.ACTION || actionType.type == ActionType.CONDITION) ) {
- throw new DecisionTableParseException( "Code description - row:" + (row + 1) + " cell number:" + (column + 1) + " - does not contain any code specification. It should !" );
- }
-
- actionType.addTemplate(column, value);
- }
-
- private void labelRow(final int row,
- final int column,
- final String value) {
- final ActionType actionType = getActionForColumn( row,
- column );
-
- if ( !value.trim().equals( "" ) && (actionType.type == ActionType.ACTION || actionType.type == ActionType.CONDITION) ) {
- this._cellComments.put( new Integer( column ),
- value );
- } else {
- this._cellComments.put( new Integer( column ),
- "From column: " + Rule.convertColNumToColName( column ) );
- }
- }
-
- private ActionType getActionForColumn(final int row,
- final int column) {
- final ActionType actionType = (ActionType) this._actions.get( new Integer( column ) );
-
- if ( actionType == null ) {
- throw new DecisionTableParseException( "Code description - row number:" + (row + 1) + " cell number:" + (column + 1) + " - does not have an 'ACTION' or 'CONDITION' column header." );
- }
-
- return actionType;
- }
-
- private void nextDataCell(final int row,
- final int column,
- final String value) {
- final ActionType actionType = getActionForColumn( row,
- column );
-
- if ( row - this._ruleRow > 1 ) {
- // Encountered a row gap from the last rule.
- // This is not part of the ruleset.
- finishRuleTable();
- processNonRuleCell( row,
- column,
- value );
- return;
- }
-
- if ( row > this._ruleRow ) {
- // In a new row/rule
- this._currentRule = createNewRuleForRow( row );
-
- this._ruleList.add( this._currentRule );
- this._ruleRow++;
- }
-
- //if the rule set is not sequential and the actionType type is PRIORITY then set the current Rule's salience paramenter with the value got from the cell
- if ( actionType.type == ActionType.PRIORITY && !this._currentSequentialFlag ) {
- this._currentRule.setSalience( new Integer( value ) );
- } else if ( actionType.type == ActionType.NAME ) // if the actionType
- // type is PRIORITY then
- // set the current
- // Rule's name
- // paramenter with the
- // value got from the
- // cell
- {
- this._currentRule.setName( value );
- } else if ( actionType.type == ActionType.DESCRIPTION ) // if the
- // actionType
- // type is
- // DESCRIPTION
- // then set the
- // current
- // Rule's
- // description
- // paramenter
- // with the
- // value got
- // from the cell
- {
- this._currentRule.setDescription( value );
- } else if ( actionType.type == ActionType.ACTIVATIONGROUP ) // if the actionType
- // type is NOLOOP
- // then set the
- // current Rule's
- // no-loop
- // paramenter with
- // the value got
- // from the cell
- {
- this._currentRule.setActivationrGroup( value );
- } else if ( actionType.type == ActionType.NOLOOP ) // if the actionType
- // type is NOLOOP
- // then set the
- // current Rule's
- // no-loop
- // paramenter with
- // the value got
- // from the cell
- {
- this._currentRule.setNoLoop( value );
- } else if ( actionType.type == ActionType.DURATION ) // if the actionType
- // type is DURATION
- // then creates a
- // new duration tag
- // with the value
- // got from the cell
- {
- createDuration( column,
- value,
- actionType );
- } else if ( actionType.type == ActionType.CONDITION || actionType.type == ActionType.ACTION ) {
- actionType.addCellValue( column, value );
- }
-
- }
-
- private Rule createNewRuleForRow(final int row) {
-
-
- Integer salience = null;
- if ( this._currentSequentialFlag ) {
- salience = new Integer( Rule.calcSalience( row ) );
- }
- final int spreadsheetRow = row + 1;
- final String name = this._currentRulePrefix + "_" + spreadsheetRow;
- final Rule rule = new Rule( name,
- salience,
- spreadsheetRow );
- rule.setComment( "From row number: " + (spreadsheetRow) );
-
- return rule;
-
- }
-
-
- // 08 - 16 - 2005 RIK: This function creates a new DURATION
- private void createDuration(final int column,
- final String value,
- final ActionType actionType) {
-
- final Duration dur = new Duration();
- dur.setSnippet( value );
- dur.setComment( cellComment( column ) );
- this._currentRule.setDuration( dur );
- }
-
-
- private boolean isCellValueEmpty(final String value) {
- return value == null || "".equals( value.trim() );
- }
-
- private String cellComment(final int column) {
- return "From column: " + Rule.convertColNumToColName( column );
- }
-
-}
\ No newline at end of file
+}
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -35,12 +35,12 @@
}
public static String getRuleName(final String ruleRow) {
- final int left = ruleRow.indexOf( RuleSheetListener.RULE_TABLE_TAG );
+ final int left = ruleRow.indexOf( DefaultRuleSheetListener.RULE_TABLE_TAG );
if ( ruleRow.indexOf( '(' ) > -1 || ruleRow.indexOf( ')' ) > -1 ) {
invalidRuleTableDef( ruleRow );
}
- return ruleRow.substring( left + RuleSheetListener.RULE_TABLE_TAG.length() ).trim();
+ return ruleRow.substring( left + DefaultRuleSheetListener.RULE_TABLE_TAG.length() ).trim();
}
private static void invalidRuleTableDef(final String ruleRow) {
@@ -119,4 +119,4 @@
}
}
-}
\ No newline at end of file
+}
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -22,6 +22,8 @@
import junit.framework.TestCase;
+import org.drools.decisiontable.parser.RuleMatrixSheetListener;
+
/**
* @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
*
@@ -35,7 +37,7 @@
public void testLoadFromClassPath() {
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final String drl = converter.compile( "/data/MultiSheetDST.xls",
- InputType.XLS );
+ InputType.XLS );
assertNotNull( drl );
@@ -48,49 +50,62 @@
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final InputStream stream = this.getClass().getResourceAsStream( "/data/MultiSheetDST.xls" );
final String drl = converter.compile( stream,
- "Another Sheet" );
+ "Another Sheet" );
assertNotNull( drl );
}
+ public void testLoadCustomListener() {
+ final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+ final InputStream stream = this.getClass().getResourceAsStream( "/data/CustomWorkbook.xls" );
+ final String drl = converter.compile( stream,
+ InputType.XLS,
+ new RuleMatrixSheetListener() );
+ assertNotNull( drl );
+ assertTrue( drl.indexOf( "\"matrix\"" ) != -1 );
+ assertTrue( drl.indexOf( "$v : FundVisibility" ) != -1 );
+ assertTrue( drl.indexOf( "FundType" ) != -1 );
+ assertTrue( drl.indexOf( "Role" ) != -1 );
+ }
+
public void testLoadCsv() {
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final InputStream stream = this.getClass().getResourceAsStream( "/data/ComplexWorkbook.csv" );
final String drl = converter.compile( stream,
- InputType.CSV );
+ InputType.CSV );
assertNotNull( drl );
-
- System.out.println(drl);
-
+
+ System.out.println( drl );
+
assertTrue( drl.indexOf( "myObject.setIsValid(1, 2)" ) > 0 );
- assertTrue( drl.indexOf( "myObject.size () > 50" ) > 0 );
-
- assertTrue( drl.indexOf("Foo(myObject.getColour().equals(red), myObject.size () > 1)") > 0);
+ assertTrue( drl.indexOf( "myObject.size () > 50" ) > 0 );
+
+ assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) > 0 );
}
public void testLoadBasicWithMergedCells() {
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final InputStream stream = this.getClass().getResourceAsStream( "/data/BasicWorkbook.xls" );
final String drl = converter.compile( stream,
- InputType.XLS );
+ InputType.XLS );
assertNotNull( drl );
-
- Pattern p = Pattern.compile(".*setIsValid\\(Y\\).*setIsValid\\(Y\\).*setIsValid\\(Y\\).*",Pattern.DOTALL | Pattern.MULTILINE);
- Matcher m = p.matcher(drl);
- assertTrue(m.matches());
-
+
+ Pattern p = Pattern.compile( ".*setIsValid\\(Y\\).*setIsValid\\(Y\\).*setIsValid\\(Y\\).*",
+ Pattern.DOTALL | Pattern.MULTILINE );
+ Matcher m = p.matcher( drl );
+ assertTrue( m.matches() );
+
assertTrue( drl.indexOf( "This is a function block" ) > -1 );
assertTrue( drl.indexOf( "global Class1 obj1;" ) > -1 );
assertTrue( drl.indexOf( "myObject.setIsValid(10-Jul-1974)" ) > -1 );
assertTrue( drl.indexOf( "myObject.getColour().equals(blue)" ) > -1 );
assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) > -1 );
-
+
assertTrue( drl.indexOf( "b: Bar() eval(myObject.size() < 3)" ) > -1 );
assertTrue( drl.indexOf( "b: Bar() eval(myObject.size() < 9)" ) > -1 );
-
- assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) <
- drl.indexOf( "b: Bar() eval(myObject.size() < 3)" ));
-
+
+ assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) < drl.indexOf( "b: Bar() eval(myObject.size() < 3)" ) );
+
}
-}
\ No newline at end of file
+}
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/model/RuleRenderTest.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/model/RuleRenderTest.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/model/RuleRenderTest.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -62,7 +62,7 @@
public void testAttributes() throws Exception {
Rule rule = new Rule("la", new Integer(42), 2);
- rule.setActivationrGroup( "foo" );
+ rule.setActivationGroup( "foo" );
rule.setNoLoop( "true" );
DRLOutput out = new DRLOutput();
Modified: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java
===================================================================
--- labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java 2006-09-18 10:39:35 UTC (rev 6258)
+++ labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java 2006-09-18 10:48:00 UTC (rev 6259)
@@ -34,7 +34,7 @@
*/
public static RuleSheetListener getRuleSheetListener(final InputStream stream) throws IOException {
final Map listners = new HashMap();
- final RuleSheetListener listener = new RuleSheetListener();
+ final RuleSheetListener listener = new DefaultRuleSheetListener();
listners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
listener );
final ExcelParser parser = new ExcelParser( listners );
@@ -42,4 +42,4 @@
stream.close();
return listener;
}
-}
\ No newline at end of file
+}
Added: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/branches/3.0.x/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
More information about the jboss-svn-commits
mailing list