23

I have to retrieve a set of column values from D/B and check it as a condition.

For example, I will have strings like "value > 2", "4 < value < 6" in a D/B column. (value is the one which is compared all the time). I will have a variable value declared in my code and I should evaluate this condition.

int value = getValue();
if (value > 2)  //(the string retrieved from the D/B)
  doSomething();

How can I do this?? Any help is muceh appreciated. Thanks.

adarshr
  • 61,315
  • 23
  • 138
  • 167

8 Answers8

35

Here is an example using the standard (Java 1.6+) scripting library:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Test {

    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("JavaScript");

        engine.eval("value = 10");
        Boolean greaterThan5 = (Boolean) engine.eval("value > 5");
        Boolean lessThan5 = (Boolean) engine.eval("value < 5");

        System.out.println("10 > 5? " + greaterThan5); // true
        System.out.println("10 < 5? " + lessThan5); // false
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 5
    I have been doing java for years, and not a month goes by when I don't look learn something new. I am not sure if this is good or bad. – NimChimpsky Jun 06 '12 at 16:10
  • It is throwing a NullPointerException on the LOC: engine.eval("value = 10"); What could be the possible reason?? – Venkateshwarrao Surabhi Jun 07 '12 at 00:12
  • @VenkateshwarraoSurabhi I am not getting that error - that probably means that `engine` is null. Are you using Java 1.6+? No typo in the engine name: "JavaScript" with upper case J and S? – assylias Jun 07 '12 at 08:01
  • I am sorry, did not know that I should click the check. Thanks for the help. :) – Venkateshwarrao Surabhi Jul 13 '12 at 19:49
  • 1
    Since all Script Engines have been removed since JDK 15 you have to add again a ScriptEngine (i.e. Nashorn) in your dependencies. See https://stackoverflow.com/a/65265993/5525384 – Paul Oct 25 '21 at 17:31
1

It's not going to be trivial: you need a parser for the expression language used in your database. If it's some standard, well-specified language, then you might be able to find one on the Internet, but if it's an in-house thing, then you may need to write your own (perhaps using a parser generator like ANTLR.)

The javax.script package contains some tools for integrating external scripting engines like a Javascript interpreter. An alternative idea would be to bring in a scripting engine and feed the expressions to that.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
1

You are basically evaluating a scripted expression. Depending what is allowed in that expression, you can get away with something very simple (regular expression identifying the groups) or very complex (embed a javascript engine?).

I'm assuming you're looking at the simple case, where the expression is: [boundary0] [operator] "value" [operator] [boundary1]

Where one, but not both of the [boundary] [operator] groups might be omitted. (And if both are presents, operator should be the same)

I would use a regular expression for that with capturing groups.

Something like: (?:(\d+)\s*([<>])\s*)?value(?:\s*([<>])\s*(\d+))?

And then: boundary1 = group(1); operator1 = group(2); operator2 = group(3); boundary2 = group(4)

ptyx
  • 4,074
  • 1
  • 19
  • 21
  • a functional example of "parsing conditions in java using regex", can be found here: https://stackoverflow.com/a/45730477/1833961 – bvdb Aug 18 '17 at 07:33
0

You should try parsing the string inside the if statement by doing something like

if(parseMyString(getValue()))
    doSomething();

In parseMyString can determine what you need to evaluate for the condition. If you don't know how to create a parser then take a look at: http://www.javapractices.com/topic/TopicAction.do?Id=87

AGE
  • 3,752
  • 3
  • 38
  • 60
0

For evaluating the conditions with maximum flexibility use a scripting language designed for embedding, for instance MVEL can parse and evaluate simple conditional expression like the ones in the question.

Using MVEL has one huge advantage over using the Scripting engine in Java 1.6+ (in particular, with JavaScript): with MVEL you can compile the scripts to bytecode, making their evaluation much more efficient at runtime.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
0

This doesn't answer your question per se; it offers an alternate solution that may effect the same result.

Instead of storing a single database column with pseudocode that defines a condition, make a table in which the schema define types of conditions that must be satisifed and the values of those conditions. This simplifies programmatic evaluation of those conditions, but it may become complicated if you have a variety of types of conditions to evaluate.

For example, you might have a table that looks like the following.

CONDITION_ID | MINIMUM | MAXIMUM | IS_PRIME  |   ETC.
______________________________________________________
      1      |    2    |   NULL  |   NULL    |   ...
      2      |    4    |    6    |   NULL    |   ...

Those row entries, respectively map to the rules value > 2 and 6 > value > 4.

This confers a number of benefits over the approach you provide.

  • Improved performance and cleanliness
  • Your conditions can be evaluated at the database level, and can be used to filter queries
  • You needn't worry about handling scenarios in which your pseudocode syntax is broken
cheeken
  • 33,663
  • 4
  • 35
  • 42
-1

The latest version of java (Java 7) allows Switch Case statements on Strings, if there are not many possible variations you could just do this or similar :

int value = getValue();
switch(myString) {
  case "value > 2" : if (value > 2) {  doSomething();} break;
  case "4 < value < 6" : if (value > 4 && value < 6) {  doSomethingElse();} break;
  default : doDefault();
}
0ddlyoko
  • 310
  • 4
  • 14
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
-4

A very good way of doing this apart from using Java 7 is using enums. Declare enum as shown below

The above enum has a collection of constants whose values are set to the strings that you expect would be returned from the database. As you can use enums in switch cases the remaining code becomes easy

enum MyEnum
{
    val1("value < 4"),val2("4<value<6");
    private String value;

    private MyEnum(String value)
    {
        this.value = value;
    }
}


public static void chooseStrategy(MyEnum enumVal)
{   
    int value = getValue();
    switch(enumVal)
    {
        case val1:
        if(value > 2){}
        break;
        case val2:
        if(4 < value && value < 6) {}
        break;
        default:
    }
}

public static void main(String[] args)
{
    String str = "4<value<6";
    chooseStrategy(MyEnum.valueOf(str));
}

All you have to do is pass your string to the enum.valueof method and it will return the appropiate enum which is put in a switch case block to perform conditional operation . In the above code you can pass any string in place of what is passed in this example

prashant
  • 1,382
  • 1
  • 13
  • 19
  • 3
    I think Uncle Bob Martin's head just exploded. – Ernest Friedman-Hill Jun 06 '12 at 18:08
  • Some feedback if welcomed: As the OP talks about pulling strings from a database your method uses a lot of code and isn't dynamic/flexible enough. If you're not certain of a possible solution you're better of not suggesting it since people will downvote your answer. However if you learn from from this question, feel free to answer similar questions or share the knowledge. ;-) – siebz0r Jun 06 '12 at 21:10
  • hmm ok I missed the point of those strings comming from the db. The point here was to show the power of enums in Java and how it can be used. Sorry guys bad miss – prashant Jun 07 '12 at 12:30