Package org.drools.decisiontable.parser

Source Code of org.drools.decisiontable.parser.RuleMatrixSheetListener

/*
* 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.
*/

package org.drools.decisiontable.parser;

import java.util.ArrayList;
import java.util.List;

import org.drools.core.util.StringUtils;
import org.drools.decisiontable.parser.DefaultRuleSheetListener;
import org.drools.template.model.Condition;
import org.drools.template.model.Consequence;
import org.drools.template.model.Rule;
import org.drools.template.model.SnippetBuilder;

/**
* @author <a href="mailto:stevearoonie@gmail.com"> Steven Williams </a><a
*         href="mailto:michael.neale@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<Condition>    _horizontalConditions   = new ArrayList<Condition>();
  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) {
    final Consequence consequence = createConsequence( 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( consequence );
  }

  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().getSingleProperty( AGENDAGROUP_TAG );
    this._action              = getProperties().getSingleProperty( ACTION_TAG );
    this._horizontalCondition = getProperties().getSingleProperty( HORIZONTALCONDITION_TAG );
    this._verticalCondition   = getProperties().getSingleProperty( VERTICALCONDITION_TAG );
    String precondition       = getProperties().getSingleProperty( PRECONDITION_TAG );
    if ( precondition != null ) {
      this._currentPrecondition = new Condition();
      this._currentPrecondition.setSnippet( precondition );
    }
  }

}
TOP

Related Classes of org.drools.decisiontable.parser.RuleMatrixSheetListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.