7

I will have a String like

('abc' != 'xyz' AND 'thy' = 'thy') OR ('ujy' = 'ujy')

The String will be able to have as many "AND" groups as it wants. There will not be any nested groups within the AND groups. All groups will ALWAYS be serparated by an OR.

I can just switch out the AND for && and OR for ||.

What I would like is to pass this String into some type of eval method and output TRUE or FALSE.

Is there anything out there that can do this?

Envin
  • 1,463
  • 8
  • 32
  • 69
  • 5
    You could use JavaScript engine to evaluate it. – Luiggi Mendoza Oct 15 '13 at 14:38
  • 1
    So the whole expression is stored in a String? An idea would be to split the String into tokens and build an abstract syntax tree out of it. Then, to evaluate the expression, you would call something like `tree.evaluate`. – helpermethod Oct 15 '13 at 14:42
  • @Luiggi This is java, not javascript – barwnikk Oct 15 '13 at 14:42
  • 1
    @barwnikk I know, and you can use JavaScript engine in Java. Also, a Java valid string is declared using `"`, not `'`. – Luiggi Mendoza Oct 15 '13 at 14:43
  • I doubt any tools exists for this but writing a simple one wouldn't be too hard. See [this](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) to start and using [String.replaceAll()](http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29). – Jonathan Drapeau Oct 15 '13 at 14:43
  • 3
    Can I just clarify, do you want to pass the entire String "('abc' != 'xyz' AND 'thy' = 'thy) OR ('ujy' = 'ujy')" into a function which will then evaluate it and return true / false? – RyanfaeScotland Oct 15 '13 at 14:45
  • @Luiggi Mendoza Ach, I have seen it's :) Sorry, my bad – barwnikk Oct 15 '13 at 14:47
  • How is that `String` buit? It might be easy enough for you to write this in Java but without more informations, you're best bet is the already voted up answers. – Jonathan Drapeau Oct 15 '13 at 14:54
  • @RyanfaeScotland The entire string – Envin Oct 15 '13 at 15:33

4 Answers4

16

You can use the built-in Javascript engine coming with the JDK1.6 to evaluate string containing math expressions.

You an give a lookup here: ScriptEngine

Here an example:

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

public class Myclass {
    public static void main(String[] args) {

        try {

            ScriptEngineManager sem = new ScriptEngineManager();
            ScriptEngine se = sem.getEngineByName("JavaScript");
            String myExpression = "('abc' == 'xyz' && 'thy' == 'thy') || ('ujy' == 'ujy')";
            System.out.println(se.eval(myExpression));

        } catch (ScriptException e) {

            System.out.println("Invalid Expression");
            e.printStackTrace();

        }
    }
}

Just remember to replace the following:

'AND' with '&&',
'OR' with '||',
'=' must be '=='

Otherwise it will not accept your expression and will throws a javax.script.ScriptException

Cirou
  • 1,420
  • 12
  • 18
2

you can use script package to achieve this like

    ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
    String[] vars = {"var1 = 'xyz'", "var2 = 'xyz'"};

    try {
        for (String var : vars) {
            engine.eval(var);
        }
        System.out.println(engine.eval("var1 == var2 "));
    } catch (ScriptException e) {
        e.printStackTrace();
    }
Jans
  • 11,064
  • 3
  • 37
  • 45
  • That would require him to parse his whole `String` and build the `vars` array and conditions `String`. Looks like it would be more complicated than doing it strictly in Java. – Jonathan Drapeau Oct 15 '13 at 14:53
1

I think you have to parse it and write custom classes for it like this

public interface StringEquals{

    public boolean equals(String s1, String s2);
}

public class Equals implements StringEquals{

    private String mS1;
    private STring mS2;

    public NotEquals(String s1, String s2){
        mS1 = s1;
        mS2 = s2;
    }


    public boolean equals(){
        return mSq1.equals(mS2);
    }
}

public class NotEquals implements StringEquals{

    private String mS1;
    private STring mS2;

    public NotEquals(String s1, String s2){
        mS1 = s1;
        mS2 = s2;
    }

    public boolean equals(){
        return !mS1.equals(mS2);
    }
}

public class AndGroup{

    private List<StringEquals> mStrings;

    public AndGroup(List<StringEquals> list){
        mStrings = list;
    }

    public boolean getResult(){
        for(StringEquals e: mStrings){
            if (!e.equals()){
                return false;
            }
        }
        return true;
    }



and a class to parse it:

public boolean eval(String evalString){
    List<AndGroup> groups = new LinkedList<AndGroup>();
    String[] ands = evalString.split("OR");
    for (String andExp : ands){
        List<StringEquals> list = new LinkedList<StringEquals>();
        String compares = andExp.split("AND");
        for (String comp: compares){
            if (comp.contains("!="){
                String[] notEqual = comp.split("!=");
                list.add(new NotEquals(notEqual[0], notEqual[1]));
            } else {
                 String[] equal = comp.split("=");
                 list.add(new Equals(equal[0], equal[1]);
            }
        }
        groups.add(new AndGroup(list));


    }
    for (AndGroup g: groups){
        if (g.getResult()){
            return true;
        }
    }
    return false;

}

not tested, but it may point you into the right direction

Rafael T
  • 15,401
  • 15
  • 83
  • 144
0

I think you can try groovy (if it's an option for you) with it's groovy.util.Eval, but first you should process your string and replace AND\OR with && and ||.

Alexander Bezrodniy
  • 8,474
  • 7
  • 22
  • 24