0

I am getting the expression from database like "Category==BWFULL && Channel==ANDROID && ver > 200". Now I am getting an input from user any value of category, channel and version. I have to validate that input with this expression given above . I can do this with multiple if else condition. But I don't want to do that. Is there any best way to evaluate this expression.

Also I can't able to do with regex because don't know how to handle ver>200. Need to clear more that the !=,>=,<=,==,>,< are present in expression and value of these Category,Channel and version are dynamic.

Actually I don't want use third party library for this. I think ScriptManager can able to execute but the expression must be "Category==\"BWFULL\" && Channel==\"ANDROID\" && ver > 200".

ScriptEngineManager manager = new ScriptEngineManager();
       ScriptEngine engine = manager.getEngineByName("js");
       engine.put("Category", "BWFULL");
       engine.put("ver",90);
       engine.put("Channel","ANDROID");

But for this I have to put inverted comma in that expression which I want to skip.It also take some time to evaluate. So is there any other solution.

Now I am using regexExpression like

Pattern.matches("([a-zA-Z]+ *== *NMW *&&)( *[a-zA-Z]+ *== *android +&&)( *[a-zA-Z]+ *== *nitrogen)", "walletcategory  ==  NMW && channel  ==android && ghb == nitrogen")

But still the problem is with value > 200 or also with the order . In above regex the order of expression is static But I want it in any order.

Now spending some effort I came up with solution using regex.

public class Main {


    public static void main(String[] args) {


//    
      String str = "walletcategory == NMW && asdfs == airtel && ghb == nitrogen && val >= 200";
        Pattern regex = Pattern.compile("[(>=)(==)(!=)(<=)]{2}|[(<)(>)]");

        evaluateTimeForForLoop(str, regex);

    }

    private static void evaluateTimeForForLoop(String str, Pattern regex) {
        long startTime = System.nanoTime();
      String[] strArr = str.split("&&");
      int len = strArr.length;
      String input[] = {"NMW","airtel","nitrogen"};
      for(int i = 0; i < len-1 ;i++) {
          String opee = strArr[i];
          String op = extractOperatorFromString(opee,regex);
          if(op != null) {
              String right = opee.substring(opee.indexOf(op)+op.length(),opee.length()).trim();
              System.out.println(evaluate(input[i], op, right));
          }

      }
      String str3 = strArr[3];
      String operator = extractOperatorFromString(str3,regex);
      if(operator != null) {
          String right = str3.substring(str3.indexOf(operator)+operator.length(),str3.length()).trim();
          System.out.println(evaluate(100, operator, Integer.parseInt(right)));
      }
        long endTime = System.nanoTime();
          System.out.println(endTime - startTime);
    }



    private static String extractOperatorFromString(String str, Pattern regex) {
        try {
            Matcher regexMatcher = regex.matcher(str);
             boolean bool = regexMatcher.matches();
            if (regexMatcher.find()) {
               return regexMatcher.group();
            } 
        } catch (PatternSyntaxException ex) {
            // Syntax error in the regular expression
        }
        return null;
    }   

    private static boolean evaluate(int left, String op, int right)
    {
            switch (op)
            {
            case "==":
                    return left == right;
            case ">":
                    return left > right;
            case "<":
                    return left < right;
            case "<=":
                    return left <= right;
            case ">=":
                    return left >= right;
            case "!=":
                    return left != right;
            default:
                    System.err.println("ERROR: Operator type not recognized.");
                    return false;
            }
    }
    private static boolean evaluate(String left, String op, String right)
    {
            switch (op)
            {
            case "==":
                    return left.equals(right);
            case "!=":
                    return !left.equals(right);
            default:
                    System.err.println("ERROR: Operator type not recognized.");
                    return false;
            }
    }

}

But still waiting for response if there is any better way to do this using regex .

dj Bravo
  • 198
  • 1
  • 3
  • 18

1 Answers1

1

Are these three options static or not? If you always have a category, channel and version, you could simply modify the database to:

requiredCategory
requiredChannel
requiredMinimalVersion (due to > 200)

and then simply evaluate these against the user parameters. But I'd rather not store any constraint in one string like you did.

maio290
  • 6,440
  • 1
  • 21
  • 38
  • The category, channel and version are dynamic. It can be any value.The expression above is like a rule which must satisfy with input from user. There can be != in expression. – dj Bravo May 04 '18 at 07:25
  • 1
    Nah, I was asking if category, channel and version are the only values you have to evaluate. Because if that's true, I'd highly recommend to use each required value out of the string to individual database fields. – maio290 May 04 '18 at 07:31
  • No there can be addition of other attribute also in future. – dj Bravo May 04 '18 at 07:34
  • Then I'd still recommend to use individual database fields for that. You'll get into hot water if you keep doing this with strings. Also you really decrease the maintainability of your application. – maio290 May 04 '18 at 07:43
  • Actually It's not possible right now to change table in database. – dj Bravo May 04 '18 at 07:51
  • Is there any reason for it? I mean you could still extract the individual required parameters with substring. But you should really consider changing the database. Assuming you have 10 arguments in the future, you'll really get a bad headache if you have to debug that. – maio290 May 04 '18 at 07:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170353/discussion-between-dj-bravo-and-maio290). – dj Bravo May 04 '18 at 09:08