1 package de.congrace.exp4j;
3 import java.util.Collection;
4 import java.util.HashSet;
8 * This is Builder implementation for the exp4j API used to create a Calculable
9 * instance for the user
14 public class ExpressionBuilder {
15 private VariableSet variables = new VariableSet();
16 private final Set<CustomFunction> customFunctions = new HashSet<CustomFunction>();
18 private String expression;
21 * Create a new ExpressionBuilder
24 * the expression to evaluate
26 public ExpressionBuilder(String expression) {
27 this.expression = expression;
31 * build a new {@link Calculable} from the expression using the supplied
34 * @return the {@link Calculable} which can be used to evaluate the
36 * @throws UnknownFunctionException
37 * when an unrecognized function name is used in the expression
38 * @throws UnparsableExpressionException
39 * if the expression could not be parsed
41 public Calculable build() throws UnknownFunctionException, UnparsableExpressionException {
42 if (expression.indexOf('=') == -1 && !variables.isEmpty()) {
44 // User supplied an expression without leading "f(...)="
45 // so we just append the user function to a proper "f()="
46 // for PostfixExpression.fromInfix()
47 StringBuilder function = new StringBuilder("f(");
48 for (String name : variables.getVariableNames()) {
49 function.append(name).append(',');
51 expression = function.deleteCharAt(function.length() - 1).toString() + ")=" + expression;
53 // create the PostfixExpression and return it as a Calculable
54 PostfixExpression delegate = PostfixExpression.fromInfix(expression, customFunctions);
55 for (Variable var : variables ) {
56 delegate.setVariable(var);
57 for (CustomFunction fn:customFunctions){
58 if (fn.getValue().equalsIgnoreCase(var.getName())){
59 throw new UnparsableExpressionException("variable '" + var + "' cannot have the same name as a custom function " + fn.getValue());
67 * add a custom function instance for the evaluator to recognize
70 * the {@link CustomFunction} to add
71 * @return the {@link ExpressionBuilder} instance
73 public ExpressionBuilder withCustomFunction(CustomFunction function) {
74 customFunctions.add(function);
78 public ExpressionBuilder withCustomFunctions(Collection<CustomFunction> functions) {
79 customFunctions.addAll(functions);
84 * set the value for a variable
87 * the variable name e.g. "x"
89 * the value e.g. 2.32d
90 * @return the {@link ExpressionBuilder} instance
92 public ExpressionBuilder withVariable(Variable value) {
98 * Provided for backwards compatibility
101 public ExpressionBuilder withVariable(String variableName, double value) {
102 variables.add(new Variable(variableName, value));
107 * set the variables names used in the expression without setting their
108 * values. Usefull for building an expression before you know the variable values.
110 * @param variableNames
111 * vararg {@link String} of the variable names used in the
113 * @return the ExpressionBuilder instance
116 public ExpressionBuilder withVariableNames(String... variableNames) {
117 for (String name : variableNames) {
118 variables.add( new Variable(name, Double.NaN) );
125 * set the values for variables
128 * a map of variable names to variable values
129 * @return the {@link ExpressionBuilder} instance
131 public ExpressionBuilder withVariables(VariableSet variables) {
132 this.variables = variables;