
src.openwfe.org.engine.impl.functions.BasicFunctions Maven / Gradle / Ivy
/*
* Copyright (c) 2001-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: BasicFunctions.java 2946 2006-07-17 08:01:26Z jmettraux $
*/
//
// BasicFunctions.java
//
// [email protected]
//
// generated with
// jtmpl 1.1.01 2004/05/19 ([email protected])
//
package openwfe.org.engine.impl.functions;
import java.text.ParseException;
import openwfe.org.Utils;
import openwfe.org.time.Time;
import openwfe.org.engine.Definitions;
import openwfe.org.engine.expool.ExpressionPool;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.expressions.FlowExpression;
/**
* Functions are static methods accepting a workitem and an array of string
* as arguments, and they return a String. The main functions for OpenWFE are
* implemented here.
*
* CVS Info :
*
$Author: jmettraux $
*
$Id: BasicFunctions.java 2946 2006-07-17 08:01:26Z jmettraux $
*
* @author [email protected]
*/
public abstract class BasicFunctions
{
private final static org.apache.log4j.Logger log = org.apache.log4j.Logger
.getLogger(BasicFunctions.class.getName());
//
// CONSTANTS & co
//
// static methods (FUNCTIONS)
/**
* Returns the count of attributes (field) the workitem has.
* fieldCount() and attributeCount() are identical functions.
*/
public static String attributeCount
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return ""+wi.getAttributes().size();
}
/**
* Returns the count of attributes (field) the workitem has.
* fieldCount() and attributeCount() are identical functions.
*/
public static String fieldCount
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return ""+wi.getAttributes().size();
}
/**
* Returns the sum of all of the numeric values given as 'args'.
*/
public static String sum
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return NumericFunctions.add(fe, wi, args);
}
/**
* This is an implementation of the lisp 'car' function, given a list as
* argument, will return the first element (see also 'cdr').
* So car('a, b, d, e') will yield 'a'.
* If a second argument is passed (the first being the list), this second
* argument will be used as the list separator (instead of the
* default ',').
* The separator regex may also be set as a variable "__list_separator__".
*/
public static String car
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringList sl = new StringList(fe, wi, args);
return sl.car();
}
/**
* This is the implementation of the 'cdr' lisp function : it will return
* the list passed as first arg without its head element.
* The second arg may be an alternate list separator, or else the list
* separator may be set at flow definition level by setting the
* "__list_separator__" variable to the appropriate string value.
*/
public static String cdr
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringList sl = new StringList(fe, wi, args);
return sl.cdr();
}
/**
* Builds a new list of an element and a list.
*
${c:cons('e' 'a, b, c')}
==> 'e, a, b, c'
*/
public static String cons
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args == null || args.length < 2) return "";
final String newElt = args[0];
final StringList sl = new StringList(fe, wi, args, 1, 2);
// sepIndex is set to 2
final String result = sl.cons(newElt);
//log.debug("cons() result >"+result+"<");
return result;
}
/**
* Returns the size of the given list attribute.
*/
public static String llen
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return ""+(new StringList(fe, wi, args)).size();
}
/**
* Builds a list out of the unique string argument awaited by this method.
* This method may be very useful when comparing lists, to make sure
* that they are formatted correctly.
*/
public static String list
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return (new StringList(fe, wi, args)).toString();
}
/**
* This function follows car() and cdr(), it will return the nth element
* of a list or '' if the list is empty or n is bigger than the list
* size.
* The first arg is the 'n', the second one is the list itself.
* So elt('2', 'a, b, c, d')
will return 'c'.
*/
public static String elt
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args == null || args.length < 2) return "";
final int index = Integer.parseInt(args[0]);
final StringList sl = new StringList(fe, wi, args, 1, 2);
// sepIndex is set to 2
return sl.elt(index);
}
/**
* This function takes a list as input and returns a the same list but with
* a different ordering.
*/
public static String shuffle
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringList sl = new StringList(fe, wi, args);
return sl.toString();
}
/**
* This function returns the given list reversed.
*/
public static String reverse
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringList sl = new StringList(fe, wi, args);
sl.reverse();
return sl.toString();
}
/**
* This function sorts the given list.
*/
public static String sort
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringList sl = new StringList(fe, wi, args);
sl.sort();
log.debug("sort() result is >"+sl.toString()+"<");
return sl.toString();
}
/**
* Returns the length of the first argument of this function.
*/
public static String len
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length < 1) return "0";
return ""+args[0].length();
}
/**
* Returns a substring of the given string
*/
public static String substring
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length < 1) return "";
final String s = args[0];
if (s.length() == 0) return "";
int i = 0;
int j = s.length();
if (args.length > 1)
i = Integer.parseInt(args[1]);
if (args.length > 2)
j = Integer.parseInt(args[2]);
if (i < 0) i = s.length() + i;
if (j < 0) j = s.length() + j;
return s.substring(i, j);
}
//
// RANDOM functions
//
/**
* Returns a random long
*/
public static String rlong
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final java.util.Random gen =
new java.util.Random(System.currentTimeMillis());
return ""+gen.nextLong();
}
/**
* Returns a random int
*/
public static String rint
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final java.util.Random gen =
new java.util.Random(System.currentTimeMillis());
return ""+gen.nextInt();
}
/**
* Returns a random double, so that 0.0 <= d < 1
*/
public static String rdouble
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final java.util.Random gen =
new java.util.Random(System.currentTimeMillis());
return ""+gen.nextDouble();
}
/**
* A generator function.
*
* "${c:range(10)}" --> 0 to 9
* "${c:range(2, 7)}" --> 2 to 8
* "${c:range(2, 7, -1)}" --> 2 to -4
*/
public static String range
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
int start = 0;
int count = 0;
int increment = 1;
try
{
if (args.length < 1) return "";
if (args.length == 1)
{
count = Integer.parseInt(args[0]);
}
else if (args.length == 2)
{
start = Integer.parseInt(args[0]);
count = Integer.parseInt(args[1]);
}
else
{
start = Integer.parseInt(args[0]);
count = Integer.parseInt(args[1]);
increment = Integer.parseInt(args[2]);
}
final StringBuffer sb = new StringBuffer();
//for (int i=start; i 0) sb.append(", ");
sb.append(""+start);
start += increment;
}
return sb.toString();
}
catch (final NumberFormatException nfe)
{
return "";
}
}
/**
* Outputs the current workflow instance id.
*/
public static String wfid
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().getWorkflowInstanceId();
}
/**
* Outputs the current workflow expression name
*/
public static String expname
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().getExpressionName();
}
/**
* Outputs the current workflow expression id
*/
public static String expid
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().getExpressionId();
}
/**
* Outputs the current flow expression id.
*/
public static String fei
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().toString();
}
/**
* Outputs the current workflow definition name.
*/
public static String wfdname
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().getWorkflowDefinitionName();
}
/**
* Outputs the current workflow definition revision.
*/
public static String wfdrevision
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return fe.getId().getWorkflowDefinitionRevision();
}
/**
* A 'proxy' for the other eval method, which is also used by the 'test'
* attribute of the 'if' expression ;
* but it's a function too.
*/
public static String eval
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length < 1) return "false";
final String s = args[0].trim().toLowerCase();
log.debug("eval(fe, wi, args) s is >"+s+"<");
if (s.equals("true")) return "true";
if (s.equals("false")) return "false";
return ""+eval(args[0]);
}
/**
* This method is used by the regular function 'eval' and by the 'if'
* expression.
*/
public static boolean eval (final String test)
{
log.debug("eval(t) test >"+test+"<");
boolean equality = true;
int i = test.indexOf("==");
int j = test.indexOf("!=");
//
// is it an inequality ?
//
int k = test.indexOf(">");
int l = test.indexOf("<");
if (l > -1) k = l;
log.debug("eval(t) k is "+k);
if (k > -1) return evalInequality(k, test);
if (j > -1)
{
i = j;
equality = false;
}
if (i < 0) return test.trim().toLowerCase().equals("true");
if (i+2 >= test.length()) return false;
final String sLeft = test.substring(0, i).trim();
final String sRight = test.substring(i+2).trim();
boolean eqResult = sLeft.equals(sRight);
if (equality) return eqResult;
return !eqResult;
}
private static boolean evalInequality
(final int operatorIndex, final String test)
{
if (operatorIndex >= test.length()-1) return false;
boolean greaterThan = (test.charAt(operatorIndex) == '>');
boolean orEquals = (test.charAt(operatorIndex+1) == '=');
log.debug("evalInequality() greaterThan : "+greaterThan);
log.debug("evalInequality() orEquals : "+orEquals);
if (orEquals && operatorIndex == test.length()-2) return false;
int offset = 2;
if (orEquals) offset = 3;
final String sLeft = test.substring(0, operatorIndex).trim();
final String sRight = test.substring(operatorIndex+offset).trim();
log.debug("evalInequality() left >"+sLeft+"<");
log.debug("evalInequality() right >"+sRight+"<");
int c = Utils.compareValues(sLeft, sRight);
log.debug("evalInequality() c is "+c);
if ( ! greaterThan) c = -1 * c;
log.debug("evalInequality() c is "+c);
if (orEquals) return c >= 0;
return c > 0;
}
/**
* Returns the hashcode for the first arg string (may be useful for
* generating some ids).
*/
public static String hashcode
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length < 1) return "";
return ""+args[0].hashCode();
}
//
// mutex functions
public static String tsm
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return testandsetmutex(fe, wi, args);
}
public static synchronized String testandsetmutex
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
String mutexName = "/__mutex__";
if (args.length > 0) mutexName = args[0];
log.debug("tsm() mutex name >"+mutexName+"< for "+fe.getId());
final Boolean b = (Boolean)getExpressionPool(fe)
.lookupVariable(fe, mutexName);
if (b == null)
{
getExpressionPool(fe).setVariable(fe, mutexName, Boolean.TRUE);
log.debug("tsm() returning 'true'");
return BooleanFunctions.S_TRUE;
}
return BooleanFunctions.S_FALSE;
}
/**
* A helper method returning the expression pool (given the flow
* expression passed to the function).
*/
public static ExpressionPool getExpressionPool (final FlowExpression fe)
{
return Definitions.getExpressionPool(fe.context());
}
//
// some debugging functions
/**
* Returns the args wrapped insed > < signs, thus "'a', 'b'"
* returns "|a| |b|".
*/
public static String d_debugargs
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
final StringBuffer sb = new StringBuffer();
for (int i=0; i"+result+"<");
return result;
}
/**
* Outputs expression pool size.
*/
public static String d_expoolsize
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return ""+getExpressionPool(fe).size();
}
/**
* Turns the input string (arg 1) to its lowercase version.
*/
public static String lowercase
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length > 0) return args[0].toLowerCase();
return "";
}
/**
* Turns the input string (arg 1) to its lowercase version
* (an alias to 'lowercase').
*/
public static String lc
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return lowercase(fe, wi, args);
}
/**
* Turns the input string (arg 1) to its lowercase version.
*/
public static String uppercase
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length > 0) return args[0].toUpperCase();
return "";
}
/**
* Turns the input string (arg 1) to its lowercase version
* (an alias to 'uppercase').
*/
public static String uc
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
return uppercase(fe, wi, args);
}
/**
* Awaits as first argument a string and as second one a regular
* expression (java flavour); will return "true" if the string matches the
* regex.
*/
public static String matches
(final FlowExpression fe, final InFlowWorkItem wi, final String[] args)
{
if (args.length < 2)
return BooleanFunctions.S_FALSE;
//log.debug("matches() string >"+args[0]+"<");
//log.debug("matches() regex >"+args[1]+"<");
return ""+args[0].matches(args[1]);
}
}