src.openwfe.org.decision.impl.SimpleDecisionTable Maven / Gradle / Ivy
/*
* Copyright (c) 2006, John Mettraux, OpenWFE.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name of the "OpenWFE" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $Id: AbstractService.java 2587 2006-05-09 09:15:59Z jmettraux $
*/
//
// SimpleDecisionTable.java
//
// [email protected]
//
// generated with
// jtmpl 1.1.01 2004/05/19 ([email protected])
//
package openwfe.org.decision.impl;
import openwfe.org.Utils;
import openwfe.org.misc.Text;
import openwfe.org.engine.workitem.Attribute;
import openwfe.org.engine.workitem.LongAttribute;
import openwfe.org.engine.workitem.StringAttribute;
import openwfe.org.engine.workitem.DoubleAttribute;
import openwfe.org.engine.workitem.BooleanAttribute;
import openwfe.org.engine.workitem.IntegerAttribute;
import openwfe.org.engine.workitem.CollectionAttribute;
import openwfe.org.engine.workitem.AttributeUtils;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.expressions.VariableMap;
import openwfe.org.engine.expressions.FlowExpression;
import openwfe.org.decision.DecisionTable;
/**
* The default implementation of a DecisionTable.
*
* CVS Info :
*
$Author$
*
$Id$
*
* @author [email protected]
*/
public class SimpleDecisionTable
implements DecisionTable
{
private final static org.apache.log4j.Logger log = org.apache.log4j.Logger
.getLogger(SimpleDecisionTable.class.getName());
//
// CONSTANTS & co
//
// FIELDS
private String[] ins = null;
private String[] outs = null;
private java.util.List rows = null;
private boolean firstMatch = true;
private boolean ignoreCase = false;
//
// CONSTRUCTORS
//
// METHODS
/**
* Sets the list of field names that are taken as input of a rule
* evaluation.
*/
public void setIns (final String[] ss)
{
this.ins = ss;
}
public void setIns (final java.util.List l)
{
this.ins = Utils.toStringArray(l);
}
/**
* Sets the list of field names that may be impacted
* by a rule.
*/
public void setOuts (final String[] ss)
{
this.outs = ss;
}
public void setOuts (final java.util.List l)
{
this.outs = Utils.toStringArray(l);
}
/**
* The list of lines (lists too) with the values that define
* the rules.
*/
public void setRows (final java.util.List l)
{
this.rows = l;
if ( ! this.ignoreCase) return;
//
// option ignore case is set, will now take care of putting
// all the 'in' values (regexes) to lowercase
// it'd be better to use the Pattern.IGNORE_CASE flag,
// but for debug output, it's better to 'see' the pattern
// in lowercase.
final java.util.Iterator it = this.rows.iterator();
while (it.hasNext())
{
final String[][] sss = (String[][])it.next();
final String[] rins = sss[0];
for (int i=0; i < rins.length; i++)
rins[i] = rins[i].toLowerCase();
}
}
/**
* If 'firstMatch' is set to true, the rule evaluation will stop
* as soon as one rule fully matches. Else all the rules will be
* evaluated, seeing their results (outs) cumulated.
*/
public void setFirstMatch (final boolean b)
{
this.firstMatch = b;
}
/**
* If this ignoreCase param is set to true, all regex matching is
* done on the rule value and the workitem value set both to lowercase.
* The default is not to ignore the case.
*/
public void setIgnoreCase (final boolean b)
{
this.ignoreCase = b;
}
//
// METHODS from DecisionTable
/* *
* Applies the rules in the decision table to the given map of fields.
* /
public void apply (final java.util.Map m)
{
final StringMapAttribute sma = AttributeUtils.map2owfe(m);
apply(sma);
return AttributeUtils.map2java(sma);
}
*/
/**
* Applies the rules in the decision table to the given map of fields.
*/
public void apply
(final InFlowWorkItem wi)
{
apply(null, wi);
}
/**
* Applies the rules in the decision table to the given map of fields.
*/
public void apply
(final FlowExpression fe, final InFlowWorkItem wi)
{
final java.util.Iterator rit = this.rows.iterator();
while (rit.hasNext())
{
final String[][] sss = (String[][])rit.next();
final String[] rins = sss[0];
final String[] routs = sss[1];
boolean valid = true;
for (int i=0; i"+fieldName+"<");
log.debug("apply() regex >"+regex+"<");
log.debug("apply() value >"+value+"<");
}
if (regex.length() > 0)
{
//if (value == null || ( ! value.matches(regex)))
if (value == null || ( ! matches(value, regex)))
{
valid = false;
break;
}
}
}
if (valid)
{
log.debug("apply() valid");
insertOuts(fe, wi, routs);
}
if (valid && firstMatch)
{
log.debug("apply() found first match");
break;
}
}
if (log.isDebugEnabled()) log.debug("apply() over.");
}
/**
* Returns true if the value matches the regex.
* If this table is set to 'ignore case', this method will take care
* of lowering the case of the value before checking the match.
*/
protected boolean matches (String value, String regex)
{
if (this.ignoreCase)
value = value.toLowerCase();
boolean negation = false;
if (regex.startsWith("!"))
{
regex = regex.substring(1);
negation = true;
}
if (log.isDebugEnabled())
log.debug("matches() regex >"+regex+"< neg ? "+negation);
boolean result = value.matches(regex);
if (negation) result = !result;
if (log.isDebugEnabled());
log.debug("matches() '"+value+"' r'"+regex+"' ? "+result);
return result;
}
/**
* This method is called upon a successful rule evaluation, it inserts
* the values specified within to the 'outs' fields.
* The dollar notation is active :-)
*/
protected void insertOuts
(final FlowExpression fe,
final InFlowWorkItem wi,
final String[] routs)
{
for (int i=0; i"+fieldName+"<");
log.debug("insertOuts() -1 value >"+value+"<");
}
fieldName = VariableMap.substitute(fe, wi, fieldName);
value = VariableMap.substitute(fe, wi, value);
if (value.length() < 1) continue;
if (log.isDebugEnabled())
{
log.debug("insertOuts() 0 fieldName >"+fieldName+"<");
log.debug("insertOuts() 0 value >"+value+"<");
}
//wi.getAttributes().setField(fieldName, value);
setValue(fe, wi, fieldName, value);
}
}
/**
* Sets the value, but takes care of looking at the fieldName prefix,
* it might be a request for setting a boolean or an integer value.
*/
protected void setValue
(final FlowExpression fe,
final InFlowWorkItem wi,
final String fieldName,
final String value)
{
boolean bVar = false;
String fName = fieldName;
Attribute aValue = null;
if (fName.startsWith("v:") ||
fName.startsWith("variable:"))
{
bVar = true;
fName = fName.substring(fName.indexOf(":") + 1);
}
final int i = fName.indexOf(":");
if (i > -1)
{
final String pfx = fName.substring(0, i).toLowerCase();
if (pfx.equals("string"))
aValue = new StringAttribute(value);
else if (pfx.equals("str"))
aValue = new IntegerAttribute(value);
else if (pfx.equals("int"))
aValue = new IntegerAttribute(value);
else if (pfx.equals("integer"))
aValue = new IntegerAttribute(value);
else if (pfx.equals("long"))
aValue = new LongAttribute(value);
else if (pfx.equals("bool"))
aValue = new BooleanAttribute(value);
else if (pfx.equals("boolean"))
aValue = new BooleanAttribute(value);
else if (pfx.equals("double"))
aValue = new DoubleAttribute(value);
// why not list attribute and map attribute ?
// later... :-)
if (aValue != null)
fName = fName.substring(i+1);
}
if (aValue == null)
aValue = new StringAttribute(value);
if (bVar && fe != null)
//
// a variable
{
//fe.bindVariable(fName, aValue.getValue());
fe.bindVariable(fName, AttributeUtils.owfe2java(aValue));
}
else
//
// a field (or there is no flowExpression for 'setting vars')
{
wi.getAttributes().setField(fName, aValue);
}
}
//
// STATIC METHODS
//
// INNER CLASSES
}