I'm looking for a relatively simpler (when compared with writing a parser) way to evaluate boolean expressions in Java, and I do not want to use the JEP library.
I have a String expression like: (x > 4 || x < 8 && p > 6) and my aim is to replace the variables with values.
Is there a way by which I can evaluate this expression?
Bear in mind that this can be any level deep so writing a parser would be very complex.
Use Apache Commons Jexl; which is exactly designed for such requirement.
http://commons.apache.org/jexl/
Using jexl (http://commons.apache.org/jexl/), you can accomplish this like this
JexlEngine jexl = new JexlEngine();
jexl.setSilent(true);
jexl.setLenient(true);
Expression expression = jexl.createExpression("(a || b && (c && d))");
JexlContext jexlContext = new MapContext();
//b and c and d should pass
jexlContext.set("b",true);
jexlContext.set("c",true);
jexlContext.set("d",true);
assertTrue((Boolean)expression.evaluate(jexlContext));
jexlContext = new MapContext();
//b and c and NOT d should be false
jexlContext.set("b",true);
jexlContext.set("c",true);
//note this works without setting d to false on the context
//because null evaluates to false
assertFalse((Boolean)expression.evaluate(jexlContext));
You could use the scripting engine in Java6 and the choose any of the popular scripting languages like Scala, Ruby, Python, Groovy, and Javascript. Than all you have to do is make sure the expression you want to evaluate is in the right language. Groovy is probably the easiest and will integrate best.
I have used this method successfully for a feature offering capabilities much like a formula / calculated column in a popular spreadsheet application.
Here is the latest resources for expression evaluation framework
The information page is at http://expressionoasis.vedantatree.com/
JUEL provides an implementation of Java's Unified Expression Language without being explicitly tied to JSP. Here's its Quick Start guide, expression evaluation (#3 on that page) is the part you're interested in.
Alternatively, Spring 3.0 provides its own (though somewhat similar) expression language. This option only makes sense if you're already using Spring, though - I wouldn't pull it in just for EL.
Try http://code.google.com/p/xpressionengine/ for open source implementation
I found the libraries listed here too complicated for my needs. I ended up using Fscript:
http://fscript.sourceforge.net/
There is a API available at http://lts.online.fr/dev/java/math.evaluator/
Example:
MathEvaluator m = new MathEvaluator("-5-6/(-2) + sqr(15+x)");
m.addVariable("x", 15.1d);
System.out.println( m.getValue() );
try Janino
http://docs.codehaus.org/display/JANINO/Home
It is very simple to use eg (taken from http://docs.codehaus.org/display/JANINO/Basic):
// Compile the expression once; relatively slow.
ExpressionEvaluator ee = new ExpressionEvaluator(
"c > d ? c : d", // expression
int.class, // expressionType
new String[] { "c", "d" }, // parameterNames
new Class[] { int.class, int.class } // parameterTypes
);
// Evaluate it with varying parameter values; very fast.
Integer res = (Integer) ee.evaluate(
new Object[] { // parameterValues
new Integer(10),
new Integer(11),
}
);
System.out.println("res = " + res);
You could try this library https://github.com/Shy-Ta/expression-evaluator-demo - the read me has a fair number of examples. The library uses java and groovy.
In addition to supporting this use case, it also supports a lot of other excel like functions. Also, it is very simple to add new functions as demonstrated in the example.
ExpressionsEvaluator evalExpr = ExpressionsFactory.create("(x > 4 || x < 8 && p > 6)");
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("x", 100);
variables.put("p", 10);
evalExpr.eval();
Related
new Vavr user here.
I am trying to pattern match a tuple of options to execute a statements if both of them are Some, in Scala I would have done this with:
val maybeThis: Option[String] = ???
val maybeThat: Option[String] = ???
(maybeThis, maybeThat) match {
case (Some(dis), Some(that)) => ???
case _ => ???
}
In Java, I am trying this approach:
Tuple2<Option<String>, Option<String>> tuple = new Tuple2<>(Option.of(...), Option.of(...));
return Match(tuple).of(
Case($Tuple2($Some($(instanceOf(String.class))), $Some($(instanceOf(String.class)))),
(someThis, someThat) -> methodWhichEatsTwoStrings(someThis.get(), someThat.get())),
Case($(), t -> run(() -> {
throw new NullPointerException(...);
})));
However, with this implementation the compiler complains that it was expecting Some<Object> instead of Some<String>, same error happens if I omit the $(instanceOf(String.class) in the pattern.
I am moderately sure this is merely a problem of proper syntax, yet I am struggling to find the correct documentation.
Where am I wrong?
Thanks
There's a vavr API construct called for comprehension that tries to mimic Scala's for comprehensions to the extent that it's possible to do in Java. With that construct you could solve your problem quite elegantly. See the For overload for handling two Options for more details. Here's an example code snippet:
String methodWhichEatsTwoStrings(String v1, String v2) {
return v1 + v2; //combine the two values in some way
}
...
Option<String> option1 = Option.some("value1");
Option<String> option2 = Option.some("value2");
String combined = For(option1, option2)
.yield((v1, v2) -> methodWhichEatsTwoStrings(v1, v2))
.getOrElseThrow(() -> new NullPointerException("reasons"));
Of course, you could use Option wrapping values of different types for option1 and option2, or combine multiple options, not just two. You could also use a different type for the return value of the yield function as well. I used String everywhere for the sake of simplicity and to conform to your original example.
I would like to add that I would try to avoid throwing NullPointerException in case one or both of the options are empty. Maybe try to use another vavr data type like Either to represent such an error case?
C# code example:
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.A = "A";
MyDynamic.B = "B";
MyDynamic.C = "C";
MyDynamic.Number = 12;
MyDynamic.MyMethod = new Func<int>(() =>
{
return 55;
});
Console.WriteLine(MyDynamic.MyMethod());
Java: ?
Any ideas why java doesn't have support for this scenario?
Java is much more strict in this case. So the short answer is no, Java doesn't have an Expando. The syntax just doesn't support that.
However there is an Expando in Groovy which is a dynamic language on top of Java.
BTW, If you're using Expando for tests, there are a lot of various Mock related solutions: EasyMock, Mockito, JMock to name a few.
I need to solve string equations in an android app, e.g. "3 + 4*(5 - log(100))". I have tried to use BeanShell for this, unfortunately I have some problems with the integer/decimal numbers. When I enter
Interpreter interpreter = new Interpreter();
String res = "9223372036854775807D";
interpreter.eval("result = " + res);
res = interpreter.get("result").toString();
res = new BigDecimal(res).stripTrailingZeros().toPlainString();
I get as result 9223372036854776000??
But when I use String res = "9223372036854775807D"; I get the correct 9223372036854775807.
I simply cannot suspitude all D to L because then I get wrong results when having somthing like 3L/2L -> 1 (but should be 1.5
Does anyone know how to handle huge numbers such as 9223372036854775807 or -9223372036854775808 or can anyone suggest an alternative to BeanShell?
Use MathEval download it from this link: http://tech.dolhub.com/code/matheval
have you tried JEP expression parser?
it is a Good mathematical expression parser purely written in Java and can parse trigonometric,logarithm functions, complex values and you can customize your own functions also...
I would like to be able to evaluate an boolean expression stored as a string, like the following:
"hello" == "goodbye" && 100 < 101
I know that there are tons of questions like this on SO already, but I'm asking this one because I've tried the most common answer to this question, BeanShell, and it allows for the evaluation of statements like this one
"hello" == 100
with no trouble at all. Does anyone know of a FOSS parser that throws errors for things like operand mismatch? Or is there a setting in BeanShell that will help me out? I've already tried Interpreter.setStrictJava(true).
For completeness sake, here's the code that I'm using currently:
Interpreter interpreter = new Interpreter();
interpreter.setStrictJava(true);
String testableCondition = "100 == \"hello\"";
try {
interpreter.eval("boolean result = ("+ testableCondition + ")");
System.out.println("result: "+interpreter.get("result"));
if(interpreter.get("result") == null){
throw new ValidationFailure("Result was null");
}
} catch (EvalError e) {
e.printStackTrace();
throw new ValidationFailure("Eval error while parsing the condition");
}
Edit:
The code I have currently returns this output
result: false
without error. What I would like it to do is throw an EvalError or something letting me know that there were mismatched operands.
In Java 6, you can dynamically invoke the compiler, as explained in this article:
http://www.ibm.com/developerworks/java/library/j-jcomp/index.html
You could use this to dynamically compile your expression into a Java class, which will throw type errors if you try to compare a string to a number.
Try the eval project
Use Janino! http://docs.codehaus.org/display/JANINO/Home
Its like eval for java
MVEL would also be useful
http://mvel.codehaus.org/
one line of code to do the evaluation in most cases:
Object result = MVEL.eval(expression, rootObj);
"rootObj" could be null, but if it's supplied you can refer to properties and methods on it without qualificiation. ie. "id" or "calculateSomething()".
You can try with http://groovy.codehaus.org/api/groovy/util/Eval.html if groovy is an option.
Like
String r = SomeThing.toExecString("new Object().toString()");
And when executed the value of r would be:
"new Object().toString() = java.lang.Object#c5e3974"
Is this even possible at all? Would it need a bunch of reflection? A built in compiler maybe?
ScriptEngine engine = new ScriptEngineManager().getEngineByName("beanshell");
Object result = engine.eval("new Object().toString();");
System.out.println(result);
You may get close to what you want using BeanShell. I ran the above code with Java 6 with BeanShell 2.0b4 and the JSR 223-based bsh-engine.jar engine on the classpath.
There is a great post here:
Generating Static Proxy Classes - http://www.javaspecialists.eu/archive/Issue180.html
Part one is enough for what you asked, I think
Don't know if you really wanted this. But your problem would be solved with this method:
String toExecString( String code ) {
return String.format(
"\"%s\" = %s#%x",
code,
code.getClass().getName(),
code.hashCode()
);
}