src.openwfe.org.engine.expressions.ValueUtils Maven / Gradle / Ivy
/*
* Copyright (c) 2005, 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: ValueUtils.java 2374 2006-03-02 12:28:01Z jmettraux $
*/
//
// ValueUtils.java
//
// [email protected]
//
// generated with
// jtmpl 1.1.00 16.08.2003 John Mettraux ([email protected])
//
package openwfe.org.engine.expressions;
import openwfe.org.xml.XmlUtils;
import openwfe.org.misc.Text;
import openwfe.org.misc.ArgParser;
import openwfe.org.engine.Definitions;
import openwfe.org.engine.expool.ExpressionPool;
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.AttributeUtils;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.functions.FunctionMap;
import openwfe.org.engine.impl.workitem.xml.XmlWorkItemCoder;
/**
* Some static methods for extracting values from fields and variables and
* fetching common values in expression attributes.
* This class doesn't need to be instantiated.
*
* CVS Info :
*
$Author: jmettraux $
*
$Id: ValueUtils.java 2374 2006-03-02 12:28:01Z jmettraux $
*
* @author [email protected]
*/
public abstract class ValueUtils
{
private final static org.apache.log4j.Logger log = org.apache.log4j.Logger
.getLogger(ValueUtils.class.getName());
//
// CONSTANTS
private final static String VALUE = "value";
private final static String FIELD_VALUE = "field-value";
private final static String VARIABLE_VALUE = "variable-value";
private final static String FUNCTION_VALUE = "function-value";
private final static String FIELD_TARGET = "field";
private final static String VARIABLE_TARGET = "variable";
private final static String OVERRIDE = "override";
private final static String TYPE = "type";
/* *
* This field name is used by expressions like 'if' and 'not'
* to determine the outcome of their action
* /
public final static String BOOLEAN_RESULT = "__boolean_result__";
*/
/**
* This workitem field if set, contains the result of a previous
* expression application.
*/
public final static String F_RESULT = "__result__";
private final static String T_LONG = "long";
private final static String T_DOUBLE = "double";
private final static String T_BOOLEAN = "boolean";
private final static String T_INTEGER = "integer";
/*
* Not in use
*
public final static String T_STRING = "string";
*/
private final static ArgParser argParser = new ArgParser();
//
// STATIC METHODS
/**
* This method is normally used by determineValue() to call
* a function; but it's also used from VariableMap for the same
* purpose, that's why it's public.
*/
public static String executeFunction
(final FlowExpression expression,
final InFlowWorkItem wi,
final String functionCall)
{
int i = functionCall.indexOf("(");
if (i < 0)
return executeFunction(expression, wi, functionCall+"()");
final String functionName = functionCall.substring(0, i);
log.debug("executeFunction() functionName >"+functionName+"<");
int j = functionCall.lastIndexOf(")");
final String rawArgs = functionCall.substring(i+1, j);
log.debug("executeFunction() rawArgs >"+rawArgs+"<");
final String[] args = argParser.parse(rawArgs);
final FunctionMap functionMap = Definitions
.getFunctionMap(expression.context());
return functionMap.eval(functionName, expression, wi, args);
}
/**
* Given a constant name like
* "openwfe.org.engine.Definitions.OPENWFE_VERSION", will return the
* value attached to this constant as a String.
*/
public static String lookupConstant
(final FlowExpression expression,
final InFlowWorkItem wi,
final String constantName)
{
final int i = constantName.lastIndexOf(".");
if (i > -1)
{
final String className = constantName.substring(0, i);
final String constName = constantName.substring(i+1);
try
{
final Class clazz = Class.forName(className);
final java.lang.reflect.Field field =
clazz.getDeclaredField(constName);
final Object o = field.get(null);
if (o != null) return o.toString();
log.debug("lookupConstant() '"+constantName+"' found null.");
}
catch (final Throwable t)
{
log.debug("lookupConstant() '"+constantName+"' failure", t);
}
}
return
"cannot lookup constant \""+constantName+"\"";
}
/**
* This method looks in the expression params to determine which value
* to return, the expression params dictate whether the value comes
* from a workitem field or an expression variable.
*/
public static Object determineValue
(final FlowExpression expression,
final InFlowWorkItem workItem)
throws
ValueException
{
return
determineValue("", expression, workItem);
}
/**
* Parsing a workitem fragment directly from the process definition
* (this method is used by GetValueExpression).
*/
public static Attribute determineWorkitemFragment
(final FlowExpression expression, final InFlowWorkItem workitem)
throws
ValueException
{
final String sContent =
expression.lookupAttribute(WithChildren.A_CONTENT, workitem);
if (sContent == null)
{
log.debug("determineWorkitemFragment() no content.");
return null;
}
log.debug("determineWorkitemFragment() sContent >"+sContent+"<");
try
{
org.jdom.Element eContent =
XmlUtils.extractXmlElement(sContent);
eContent = XmlUtils.getFirstChild(eContent);
if (eContent == null)
{
log.debug("determineWorkitemFragment() no first child.");
return null;
}
return
((XmlWorkItemCoder)Definitions
.getXmlCoder(expression.context()))
.decodeAttribute(eContent);
}
catch (final Exception e)
{
throw new ValueException
("Failed to extract workitem fragment", e);
}
}
/**
* This method looks in the expression params to determine which value
* to return, the expression params dictate whether the value comes
* from a workitem field or an expression variable, a prefix is given for
* the key lookup in the params of the expression.
*/
public static Object determineValue
(final String prefix,
final FlowExpression expression,
final InFlowWorkItem workItem)
throws
ValueException
{
log.debug("determineValue() prefix >"+prefix+"<");
//
// where should the value be taken from ?
String value = expression
.lookupAttribute(prefix+VALUE, workItem);
String valueFieldName = expression
.lookupAttribute(prefix+FIELD_VALUE, workItem);
String valueVariableName = expression
.lookupAttribute(prefix+VARIABLE_VALUE, workItem);
if (value == null && prefix.equals(""))
//
// nested XML value
//
{
value = expression.lookupAttribute(WithChildren.A_VALUE, workItem);
log.debug("determineValue() nested value >"+value+"<");
if (value == null &&
expression.getAttributes().containsKey(WithChildren.A_CONTENT))
{
return determineWorkitemFragment(expression, workItem);
}
}
String functionValue = expression
.lookupAttribute(prefix+FUNCTION_VALUE, workItem);
if (functionValue != null)
{
functionValue = executeFunction
(expression, workItem, functionValue);
}
if (value == null &&
valueFieldName == null &&
valueVariableName == null &&
functionValue == null)
{
throw new ValueException
("There is no attribute '"+prefix+VALUE+
"', '"+prefix+FIELD_VALUE+
"' or '"+prefix+VARIABLE_VALUE+
"' or '"+prefix+FUNCTION_VALUE+
"'. Cannot determine value");
}
log.debug("value >"+value+"<");
log.debug("value of field >"+valueFieldName+"<");
log.debug("value of variable >"+valueVariableName+"<");
log.debug("functionValue >"+functionValue+"<");
//
// extract value
Object variableValue = null;
if (value != null)
{
variableValue = value;
String type = expression.lookupAttribute(TYPE, workItem);
if (type != null)
//
// enforce a certain type
{
log.debug("type >"+type+"<");
if (type.equals(T_BOOLEAN))
variableValue = new BooleanAttribute(value);
else if (type.equals(T_INTEGER))
variableValue = new IntegerAttribute(value);
else if (type.equals(T_LONG))
variableValue = new LongAttribute(value);
else if (type.equals(T_DOUBLE))
variableValue = new DoubleAttribute(value);
}
}
else if (valueVariableName != null)
{
variableValue = expression.lookupVariable(valueVariableName);
}
else if (valueFieldName != null)
{
//variableValue = workItem.getAttribute(valueFieldName);
final Object fv0 =
workItem.getAttribute(valueFieldName);
final String fv1 = ((AbstractFlowExpression)expression)
.substituteText("${f:"+valueFieldName+"}", workItem);
log.debug("fv1 is >"+fv1+"<");
if (fv0 == null)
{
log.debug("fv0 is null");
}
else
{
log.debug
("fv0 is >"+fv0+
"< ("+fv0.getClass().getName()+")");
}
//if (fv1 != null && ( ! fv1.equals("")))
// variableValue = fv1;
//else
// variableValue = fv0;
if (fv0 != null)
variableValue = fv0;
else if ((fv1 != null) && (fv1.length() > 0))
variableValue = fv1;
}
else if (functionValue != null)
{
variableValue = functionValue;
}
log.debug("value is >"+variableValue+"<");
if (value != null)
log.debug("value.class is >"+variableValue.getClass()+"<");
//
// the end
return variableValue;
}
/**
* This method determines and sets a value in a workitem field or
* in the expression variable.
*
* @return a map of variables or null
*/
public static java.util.Map determineAndSetTarget
(final FlowExpression expression,
final InFlowWorkItem workItem,
final Object value)
throws
ValueException
{
return doDetermineAndSetTarget
("",
expression,
workItem,
value);
}
/**
* This method determines and sets a value in a workitem field or
* in the expression variable, a prefix dictates which key in the
* expression params is used for the determination.
*
* @return a map of variables or null
*/
public static java.util.Map determineAndSetTarget
(final String prefix,
final FlowExpression expression,
final InFlowWorkItem workItem,
final Object value)
throws
ValueException
{
return doDetermineAndSetTarget
(prefix,
expression,
workItem,
value);
}
/*
* This method determines and sets a value in a workitem field or
* in the expression variable, a prefix dictates which key in the
* expression params is used for the determination.
*/
private static java.util.Map doDetermineAndSetTarget
(String prefix,
final FlowExpression expression,
final InFlowWorkItem workItem,
final Object value)
throws
ValueException
{
if (value == null)
log.debug("doDetermineAndSetTarget() 'unset'");
if (prefix == null) prefix = "";
String fieldName =
expression.lookupAttribute(prefix+FIELD_TARGET, workItem);
String variableName =
expression.lookupAttribute(prefix+VARIABLE_TARGET, workItem);
if (fieldName == null &&
variableName == null)
{
throw new ValueException
("Expression should set a value but which one ? "+
"there is no paremeter '"+prefix+FIELD_TARGET+
"' or '"+prefix+VARIABLE_TARGET+"' given.");
}
if (variableName != null)
{
log.debug
("doDetermineAndSetTarget() variableName >"+variableName+"<");
//
// should we at this point turn a value that is an instance of
// Attribute into some String ?
//
if (value != null)
{
log.debug
("doDetermineAndSetTarget() '"+variableName+
"' -> "+value.getClass().getName());
}
log.debug
("doDetermineAndSetTarget() '"+variableName+
"' -> '"+value+"'");
setVariable(expression, variableName, value);
//
// AND return a new map containing the same binding...
//
final java.util.Map result = new java.util.HashMap(1);
result.put(variableName, value);
return result;
}
//
// fieldName != null
//
//
// determine if field value can be overriden
boolean override = true;
String sOverride = expression.lookupAttribute(OVERRIDE, workItem);
if (sOverride != null &&
sOverride.trim().toLowerCase().equals("false"))
{
override = false;
}
//
// determine if field currently has a value
Object currentValue = workItem.getAttributes().get(fieldName);
if (currentValue != null && ! override)
{
log.debug
("doDetermineAndSetTarget() "+
"cannot override workitem's field value");
return null;
}
//
// set value
/*
if (value == null)
{
workItem.getAttributes().remove(fieldName);
}
else
{
Attribute aValue = null;
if (value instanceof Attribute)
aValue = (Attribute)value;
else
aValue = new StringAttribute(value.toString());
workItem.getAttributes().put(fieldName, aValue);
}
*/
workItem.getAttributes().setField(fieldName, value);
return null;
}
/**
* Determines which expression variable or workitem field should
* be incremented and increments it with the given value.
*/
public static void determineAndIncrementTarget
(final FlowExpression expression,
final InFlowWorkItem workItem,
Object value)
throws
ValueException
{
if (value == null) return;
String fieldName =
expression.lookupAttribute(FIELD_TARGET, workItem);
String variableName =
expression.lookupAttribute(VARIABLE_TARGET, workItem);
if (fieldName == null &&
variableName == null)
{
throw new ValueException
("Expression should set a value but which one ? "+
"there is no paremeter '"+FIELD_TARGET+
"' or '"+VARIABLE_TARGET+"' given.");
}
if (variableName != null)
{
Object currentValue = expression.lookupVariable(variableName);
value = increment(currentValue, value);
//expression.getExpressionPool()
// .setVariable(expression, variableName, value);
setVariable(expression, variableName, value);
}
else if (fieldName != null)
{
Object currentValue = workItem.getAttributes().get(fieldName);
value = increment(currentValue, value);
workItem.getAttributes().put(fieldName, (Attribute)value);
}
}
/*
* used by doDetermineAndSetTarget() and by determineAndIncrementTarget()
*/
private static void setVariable
(final FlowExpression expression,
final String variableName ,
final Object value)
{
String vName = variableName;
FlowExpression containingExpression = null;
if (variableName.startsWith("./"))
//
// forced to bound locally
{
containingExpression = expression;
vName = variableName.substring(2);
}
else
//
// regular binding
{
containingExpression = expression.getExpressionPool()
.lookupContainingEnvironment(expression, vName);
if (containingExpression == null)
containingExpression = expression;
}
// do the bind
expression.getExpressionPool()
.setVariable(containingExpression, vName, value);
}
private static Object increment (Object val, Object inc)
{
Object originalVal = val;
val = refineValue(val);
inc = refineValue(inc);
Object result = refinedIncrement(val, inc);
if (originalVal instanceof Attribute)
{
if (result instanceof Long)
return new LongAttribute((Long)result);
if (result instanceof Double)
return new DoubleAttribute((Double)result);
return new StringAttribute(result.toString());
}
log.debug("increment() new value = "+result);
return result;
}
private static Object refineValue (final Object o)
{
if (o == null) return "";
try
{
long l = Long.parseLong(o.toString());
return new Long(l);
}
catch (NumberFormatException nfe)
{
// ignore
}
try
{
double d = Double.parseDouble(o.toString());
return new Double(d);
}
catch (NumberFormatException nfe)
{
// ignore
}
return o.toString();
}
private static double toDouble (Object o)
{
return Double.parseDouble(o.toString());
}
private static int toInt (Object o)
{
return Integer.parseInt(o.toString());
}
private static Object refinedIncrement (Object val, Object inc)
{
if (val instanceof String || inc instanceof String)
return val.toString() + inc.toString();
if (val instanceof Double || inc instanceof Double)
return new Double(toDouble(val) + toDouble(inc));
return new Integer(toInt(val) + toInt(inc));
}
/**
* Looks for a boolean result field in the workitem.
* Used by the 'if' and the 'when' expression.
*/
public static boolean lookupBooleanResult (final InFlowWorkItem wi)
throws ReplyException
{
//Attribute a = wi.getAttributes().get(ValueUtils.BOOLEAN_RESULT);
Attribute a = wi.getAttributes().get(F_RESULT);
if (a == null)
{
throw new ReplyException
("lookupBooleanVariable() no boolean result found");
}
//log.debug("o.class is "+o.getClass().getName());
if (a instanceof BooleanAttribute)
return ((BooleanAttribute)a).booleanValue();
return (a.toString().toLowerCase().equals("true"));
/*
throw new ReplyException
("lookupBooleanVariable() boolean value expected, "+
"found "+a.getClass());
*/
}
/**
* removes any boolean result variable in this expression
* (used by CondExpression)
*/
public static void cleanResult (final InFlowWorkItem wi)
{
wi.getAttributes().remove(F_RESULT);
}
/**
* Sets the field '__boolean_result__' in the workitem.
*/
public static void setBooleanResult
(final InFlowWorkItem wi, final boolean result)
{
log.debug
("setBooleanResult() '"+result+"' for "+wi.getLastExpressionId());
wi.getAttributes().put(F_RESULT, new BooleanAttribute(result));
}
/**
* Sets the field '__result__' in the workitem.
*/
public static void setBooleanResult
(final InFlowWorkItem wi, Boolean result)
{
setBooleanResult(wi, result.booleanValue());
}
/**
* Sets the field '__result__' in the workitem.
*/
public static void setResult
(final InFlowWorkItem wi, final Object result)
{
wi.getAttributes().put(F_RESULT, AttributeUtils.java2owfe(result));
// the method java2owfe leaves the result untouched if
// it's already an Attribute
}
/* why not ? :
public static void setResult
(final InFlowWorkItem wi, final Object[] result)
{
}
*/
/**
* Returns the result held in the field '__result__'.
*/
public static Attribute getResult (final InFlowWorkItem wi)
{
return wi.getAttributes().get(F_RESULT);
}
}