Evaluate String as a condition Java

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.

Upvotes: 23

Views: 20858

Answers (8)

NimChimpsky
NimChimpsky

Reputation: 47310

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();
}

Upvotes: -1

&#211;scar L&#243;pez
&#211;scar L&#243;pez

Reputation: 236170

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.

Upvotes: 0

prashant
prashant

Reputation: 1445

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

Upvotes: -4

cheeken
cheeken

Reputation: 34695

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

Upvotes: 0

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81734

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.

Upvotes: 1

assylias
assylias

Reputation: 328923

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
    }
}

Upvotes: 35

AGE
AGE

Reputation: 3792

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

Upvotes: 0

ptyx
ptyx

Reputation: 4164

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)

Upvotes: 1

Related Questions