1 package net.sf.openrocket.util.exp4j;
3 import java.util.Collection;
4 import java.util.HashSet;
5 import java.util.LinkedHashMap;
7 import java.util.Map.Entry;
11 * This is Builder implementation for the exp4j API used to create a Calculable
12 * instance for the user
17 public class ExpressionBuilder {
18 private final Map<String, Double> variables = new LinkedHashMap<String, Double>();
19 private final Set<CustomFunction> customFunctions = new HashSet<CustomFunction>();
21 private String expression;
24 * Create a new ExpressionBuilder
27 * the expression to evaluate
29 public ExpressionBuilder(String expression) {
30 this.expression = expression;
34 * build a new {@link Calculable} from the expression using the supplied
37 * @return the {@link Calculable} which can be used to evaluate the
39 * @throws UnknownFunctionException
40 * when an unrecognized function name is used in the expression
41 * @throws UnparsableExpressionException
42 * if the expression could not be parsed
44 public Calculable build() throws UnknownFunctionException, UnparsableExpressionException {
45 if (expression.indexOf('=') == -1 && !variables.isEmpty()) {
47 // User supplied an expression without leading "f(...)="
48 // so we just append the user function to a proper "f()="
49 // for PostfixExpression.fromInfix()
50 StringBuilder function = new StringBuilder("f(");
51 for (String var : variables.keySet()) {
52 function.append(var).append(',');
54 expression = function.deleteCharAt(function.length() - 1).toString() + ")=" + expression;
56 // create the PostfixExpression and return it as a Calculable
57 PostfixExpression delegate = PostfixExpression.fromInfix(expression, customFunctions);
58 for (String var : variables.keySet()) {
59 if (variables.get(var) != null) {
60 delegate.setVariable(var, variables.get(var));
62 for (CustomFunction custom:customFunctions){
63 if (custom.getValue().equals(var)){
64 throw new UnparsableExpressionException("variable '" + var + "' cannot have the same name as a custom function " + custom.getValue());
72 * add a custom function instance for the evaluator to recognize
75 * the {@link CustomFunction} to add
76 * @return the {@link ExpressionBuilder} instance
78 public ExpressionBuilder withCustomFunction(CustomFunction function) {
79 customFunctions.add(function);
83 public ExpressionBuilder withCustomFunctions(Collection<CustomFunction> functions) {
84 customFunctions.addAll(functions);
89 * set the value for a variable
92 * the variable name e.g. "x"
94 * the value e.g. 2.32d
95 * @return the {@link ExpressionBuilder} instance
97 public ExpressionBuilder withVariable(String variableName, double value) {
98 variables.put(variableName, value);
103 * set the variables names used in the expression without setting their
106 * @param variableNames
107 * vararg {@link String} of the variable names used in the
109 * @return the ExpressionBuilder instance
111 public ExpressionBuilder withVariableNames(String... variableNames) {
112 for (String variable : variableNames) {
113 variables.put(variable, null);
119 * set the values for variables
122 * a map of variable names to variable values
123 * @return the {@link ExpressionBuilder} instance
125 public ExpressionBuilder withVariables(Map<String, Double> variableMap) {
126 for (Entry<String, Double> v : variableMap.entrySet()) {
127 variables.put(v.getKey(), v.getValue());