Expression4j Expression4J

Sample > Custom expression element

About
Documentation
Sample
    Simple expression
    Agregated expression
    Predefined function
    User define function
    Custom element
    Custom operator
    External configuration
Download

Create a custom element like string, boolean or matrix

A custom expression element is constitued by :
  • the ExpressionElement class used to parse the custom element
  • the MathematicalElement class used to store the custom element value.
  • all OperatorImpl class used to compute custom element with other predefine element or custom element
Expression does not support space. If spaces are present in the expression, the parsin will generate an error.

Add String element to Expression4j

  1. Define the MathematicalElement used to store String element.

    public class StringMathematicalElement implements MathematicalElement {

    //parameter value used to store element in a config file.
    public final static String STRING_VALUE = "stringValue";

    private String stringValue;

    public StringMathematicalElement(String value) {
    super();
    this.stringValue = value;
    }

    public double getComplexValue() throws MathematicalException {
    //no used
    return 0;
    }

    public Properties getProperties() {
    //used to store objet in xml file (used by configuration manager)
    Properties result = new Properties();
    result.put(STRING_VALUE,stringValue);
    return result;
    }

    public double getRealValue() {
    //not used
    return 0;
    }

    public int getType() {
    //create a new constant for String type.
    return 5;
    }

    public Object getValue() {
    //get the value of the String as an Object.
    return stringValue;
    }

    public void setProperties(Properties properties) {
    //used to store objet in xml file (used by configuration manager)
    stringValue = (String) properties.getProperty(STRING_VALUE);
    }

    }
  2. Define the ExpressionElement class used to parse the new String element. String element are delimited by < ' >.
    The sample is simple and does not support ' in sting.

    public class StringExpressionElement implements ExpressionElement {

    public StringExpressionElement() {
    super();
    }

    /* (non-Javadoc)
    * @see fr.expression4j.basic.ExpressionElement#parseElement(java.lang.String,
    fr.expression4j.basic.ParseInfo)
    */
    public boolean parseElement(String expression, ExpressionModel expressionModel,
    ParseInfo parseInfo, Catalog catalog, List functionParameters,
    int priorityOperatorLevel) throws ParsingException {
    int startPos = parseInfo.getEndPos();
    int currentPos = parseInfo.getEndPos();

    //check if current position start with a '
    if (ExpressionElementUtil.checkPosition(expression,currentPos) &&
    expression.charAt(currentPos) == '\'') {
    currentPos ++;

    //lokk for the end '
    while (ExpressionElementUtil
    .checkPosition(expression,currentPos) &&
    expression.charAt(currentPos) != '\'') {
    currentPos ++;
    }

    if (expression.charAt(currentPos) != '\'') {
    //not found the end of the string.
    return false;
    }

    //found the ending '
    //create the corresponding TreeElement of the StringExpressionElement
    String valueString = expression
    .substring(startPos+1,currentPos);
    MathematicalElement value =
    new StringMathematicalElement(valueString);
    TreeElement result = new TreeElement(TreeElement.TREE_ELEMENT_TYPE_VALUE,
    null,null,value,getName(),null,null);
    parseInfo.setTreeElement(result);
    parseInfo.setEndPos(currentPos+1);
    return true;
    }

    return false;

    }

    public String getName() {
    return "StringExpressionElement";
    }

    public MathematicalElement evaluate(TreeElement element, Catalog catalog,
    OperatorManager operatorManager, Parameters parameters,
    ExpressionModel model) throws EvalException {
    //throw an exception.
    //evaluate method is reserved for function or specific custom expression element
    //like "if" operator.
    throw new EvalException("Cannot evaluate " + getName());
    }

    public String toString(TreeElement element, ExpressionModel expressionModel) {
    return "<" + getName() + ">";
    }

    }

  3. Define OperatorImpl class. Two operators is define. Operator "+" to manage String concatenation and operator "+"
    to manage Integer and String concatenation.

    public class OperatorPlusStringReal implements OperatorImpl {

    public OperatorPlusStringReal() {
    super();
    }

    public MathematicalElement compute(MathematicalElement leftElement,
    MathematicalElement rightElement) throws EvalException {

    StringBuffer result = new StringBuffer();

    if (leftElement.getType() == 1) {
    result.append(leftElement.getRealValue());
    }
    else {
    result.append(leftElement.getValue());
    }

    if (rightElement.getType() == 1) {
    result.append(rightElement.getRealValue());
    }
    else {
    result.append(rightElement.getValue());
    }

    return new StringMathematicalElement(result.toString());
    }

    public int getLeftOperandeType() {
    return 5;
    }

    public String getOperatorName() {
    return "plus";
    }

    public int getRightOperandeType() {
    return 1;
    }

    public boolean isUnaryOperator() {
    return false;
    }

    }


    public class OperatorPlusStringString implements OperatorImpl {

    public OperatorPlusStringString() {
    super();
    }

    public MathematicalElement compute(MathematicalElement leftElement,
    MathematicalElement rightElement) throws EvalException {
    if (leftElement.getType() != 5) {
    throw new EvalException(
    "Left element is not a StringMathematicalElement");
    }

    if (rightElement.getType() != 5) {
    throw new EvalException(
    "
    Right element is not a StringMathematicalElement");
    }

    StringBuffer result = new StringBuffer((String)
    leftElement.getValue());
    result.append((String) rightElement.getValue());
    return new StringMathematicalElement(result.toString());
    }

    public int getLeftOperandeType() {
    return 5;
    }

    public String getOperatorName() {
    return "plus";
    }

    public int getRightOperandeType() {
    return 5;
    }

    public boolean isUnaryOperator() {
    return false;
    }

    }
  4. Sample class who use the new StringExpressionElement.
    public class CustomExpressionElement2 {


    public static void main(String[] args) {
    try {
    //create a specific expression model
    ExpressionModel stringExpressionModel =
    ExpressionModelFactory.createExpressionModel("StringExpressionModel");

    //add binary operator supported by the specific expression model
    stringExpressionModel.addBinaryOperator(new OperatorPlus(),1);

    //add custom expression element
    stringExpressionModel.addExpressionElement(new StringExpressionElement(),1);

    //add standardexpression element
    stringExpressionModel.addExpressionElement(
    new ComplexOrRealExpressionElement(),2);
    stringExpressionModel.addExpressionElement(
    new
    FunctionExpressionElement(),3);
    stringExpressionModel.addExpressionElement(
    new ConstantOrVariableExpressionElement(),4);
    stringExpressionModel.addExpressionElement(
    new ParenthesisExpressionElement(),5);

    //create a specific operator manager
    OperatorManager stringOperatorManager =
    OperatorManagerFactory.createOperatorManager("stringOperatorManager");

    //add operator specific to previous model
    stringOperatorManager.addOperatorImpl(new OperatorPlusStringString());
    stringOperatorManager.addOperatorImpl(new OperatorPlusStringReal());

    //create an expression with the specific expression model
    Expression expression =
    ExpressionFactory.createExpression("f(x)='toto'+x+'titi'",
    ExpressionFactory.getCatalog(),stringExpressionModel);
    Expression expression2 =
    ExpressionFactory.createExpression("g(x,y)=f(y)+' '+(x+' '+f(x+y))",
    ExpressionFactory.getCatalog(),stringExpressionModel);

    //compute expression
    Parameters parameters = ExpressionFactory.createParameters();
    parameters.addParameter("x",new StringMathematicalElement("test"));
    parameters.addParameter("y",new StringMathematicalElement("une valeur"));
    MathematicalElement result =
    expression2.evaluate(stringOperatorManager,parameters);

    //display result
    System.out.println("result: " + result.getValue());

    //compute expression with a real
    for (int i=0; i<10; i++) {
    parameters.addParameter("x",NumberFactory.createReal(i));
    parameters.addParameter("y",new StringMathematicalElement("une valeur"));
    result = expression2.evaluate(stringOperatorManager,parameters);

    //display result
    System.out.println("result: " + result.getValue());
    }


    }
    catch (Exception e) {
    System.out.println("Error: " + e);
    }

    }

    }



 
SourceForge.net Logo Support This Project