/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java

https://gitlab.com/MichelZuniga/drools · Java · 192 lines · 109 code · 17 blank · 66 comment · 17 complexity · ee2f0cd451a3e60abe53192986bf1777 MD5 · raw file

  1. /*
  2. * Copyright 2005 JBoss Inc
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.drools.decisiontable.parser;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. import org.drools.core.util.StringUtils;
  20. import org.drools.decisiontable.parser.DefaultRuleSheetListener;
  21. import org.drools.template.model.Condition;
  22. import org.drools.template.model.Consequence;
  23. import org.drools.template.model.Rule;
  24. import org.drools.template.model.SnippetBuilder;
  25. /**
  26. * href="mailto:michael.neale@gmail.com"> Michael Neale </a>
  27. *
  28. * Define a ruleset spreadsheet which contains a matrix style decision tables.
  29. *
  30. * This is an example of a custom RuleSheetListener. It differs from the standard
  31. * decision table in the following ways:
  32. * - AgendaGroup property so that all rules fall within the same agenda-group
  33. * - Precondition property which specifies a condition that is always included
  34. * if a rule is being generated
  35. * - Action property. Each cell within the decision table causes this action
  36. * to be triggered
  37. * - HorizontalCondition property. Each column header in the matrix
  38. * applies this condition
  39. * - VerticalCondition property. Each row header in the matrix applies this
  40. * condition
  41. *
  42. * A table is identifed by a cell beginning with the text "RuleTable".
  43. * The cells after RuleTable in the same row identify the Horizontal Conditions.
  44. * The cells after RuleTable in the same column identify the Vertical Conditions.
  45. * The cells with the matrix identify the actions.
  46. * Wherever an action cell exists for a Vertical/Horizontal condition intersection
  47. * the following rule is created:
  48. * rule "rule_row_col"
  49. * agenda-group AgendaGroup
  50. * when
  51. * Precondition
  52. * VerticalCondition
  53. * HorizontalCondition
  54. * then
  55. * Action
  56. * end
  57. */
  58. public class RuleMatrixSheetListener extends DefaultRuleSheetListener {
  59. //keywords
  60. public static final String AGENDAGROUP_TAG = "AgendaGroup";
  61. public static final String PRECONDITION_TAG = "Precondition";
  62. public static final String ACTION_TAG = "Action";
  63. public static final String HORIZONTALCONDITION_TAG = "HorizontalCondition";
  64. public static final String VERTICALCONDITION_TAG = "VerticalCondition";
  65. //state machine variables for this parser
  66. private int ruleTableRow;
  67. private int ruleTableColumn;
  68. private String _currentAgendaGroup;
  69. private Condition _currentPrecondition;
  70. private String _action;
  71. private String _horizontalCondition;
  72. private String _verticalCondition;
  73. private List<Condition> _horizontalConditions = new ArrayList<Condition>();
  74. private Condition _currentVerticalCondition;
  75. private boolean isInRuleTable;
  76. private Rule firstRule;
  77. public void newCell(final int row,
  78. final int column,
  79. final String value,
  80. final int mergedColStart) {
  81. // if we aren't in the rule table just use the default handling
  82. // (add a property)
  83. if ( ! isInRuleTable ) {
  84. super.newCell( row, column, value, mergedColStart );
  85. return;
  86. }
  87. // ignore empty cells
  88. if ( StringUtils.isEmpty( value ) ) {
  89. return;
  90. }
  91. //Horizontal header column
  92. //Create a new condition using HorizontalCondition as the template
  93. //and save it for later use
  94. if ( row == (ruleTableRow) && column > ruleTableColumn ) {
  95. _horizontalConditions.add( createCondition( value, _horizontalCondition ) );
  96. }
  97. //Vertical header column
  98. //Create a new condition using VerticalCondition as the template
  99. //and set it as the current condition
  100. else if ( row > (ruleTableRow) && column == ruleTableColumn ) {
  101. _currentVerticalCondition = createCondition( value, _verticalCondition );
  102. }
  103. //Intersection column
  104. //Create a new Consequence
  105. else if ( row > (ruleTableRow) && column > ruleTableColumn ) {
  106. createRule( row, column, value );
  107. }
  108. }
  109. private void createRule(final int row,
  110. final int column,
  111. final String value) {
  112. final Consequence consequence = createConsequence( value );
  113. Rule rule = firstRule;
  114. if ( rule == null ) {
  115. rule = new Rule( "rule_" + row + "_" + column,
  116. null,
  117. row );
  118. addRule( rule );
  119. } else {
  120. firstRule = null;
  121. rule.setName( "rule_" + row + "_" + column );
  122. }
  123. rule.setAgendaGroup( this._currentAgendaGroup );
  124. rule.addCondition( this._currentPrecondition );
  125. rule.addCondition( _currentVerticalCondition );
  126. rule.addCondition( (Condition) _horizontalConditions.get( column - (ruleTableColumn + 1) ) );
  127. rule.addConsequence( consequence );
  128. }
  129. private Consequence createConsequence(final String value) {
  130. final SnippetBuilder snip = new SnippetBuilder( _action );
  131. final String result = snip.build( value );
  132. final Consequence consequence = new Consequence();
  133. consequence.setSnippet( result );
  134. return consequence;
  135. }
  136. private Condition createCondition(final String value,
  137. final String conditionTemplate) {
  138. SnippetBuilder snip = new SnippetBuilder( conditionTemplate );
  139. String result = snip.build( value );
  140. Condition condition = new Condition();
  141. condition.setSnippet( result );
  142. return condition;
  143. }
  144. public void newRow(int rowNumber,
  145. int columns) {
  146. // nothing to do here
  147. }
  148. public void finishSheet() {
  149. // nothing to do here
  150. }
  151. protected void postInitRuleTable(int row,
  152. int column,
  153. String value) {
  154. this.firstRule = getCurrentRule();
  155. }
  156. /**
  157. * This gets called each time a "new" rule table is found.
  158. */
  159. protected void preInitRuleTable(final int row,
  160. final int column,
  161. final String value) {
  162. this.ruleTableColumn = column;
  163. this.ruleTableRow = row;
  164. this.isInRuleTable = true;
  165. this._currentAgendaGroup = getProperties().getSingleProperty( AGENDAGROUP_TAG );
  166. this._action = getProperties().getSingleProperty( ACTION_TAG );
  167. this._horizontalCondition = getProperties().getSingleProperty( HORIZONTALCONDITION_TAG );
  168. this._verticalCondition = getProperties().getSingleProperty( VERTICALCONDITION_TAG );
  169. String precondition = getProperties().getSingleProperty( PRECONDITION_TAG );
  170. if ( precondition != null ) {
  171. this._currentPrecondition = new Condition();
  172. this._currentPrecondition.setSnippet( precondition );
  173. }
  174. }
  175. }