{
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitBoolExpression(@NotNull SimpleBooleanParser.BoolExpressionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitBool(@NotNull SimpleBooleanParser.BoolContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitNotExpression(@NotNull SimpleBooleanParser.NotExpressionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitParse(@NotNull SimpleBooleanParser.ParseContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitParenExpression(@NotNull SimpleBooleanParser.ParenExpressionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitDoubleQuotedText(@NotNull SimpleBooleanParser.DoubleQuotedTextContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitBinaryExpression(@NotNull SimpleBooleanParser.BinaryExpressionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitComparator(@NotNull SimpleBooleanParser.ComparatorContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitDecimalExpression(@NotNull SimpleBooleanParser.DecimalExpressionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitBinary(@NotNull SimpleBooleanParser.BinaryContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitContextVariables(@NotNull SimpleBooleanParser.ContextVariablesContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitText(@NotNull SimpleBooleanParser.TextContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitQuotedText(@NotNull SimpleBooleanParser.QuotedTextContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitComparatorExpression(@NotNull SimpleBooleanParser.ComparatorExpressionContext ctx) { return visitChildren(ctx); }
+}
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.interp b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.interp
new file mode 100644
index 0000000000..f234a9fef6
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.interp
@@ -0,0 +1,77 @@
+token literal names:
+null
+'&'
+'|'
+'$!'
+'true'
+'false'
+'>'
+'>='
+'<'
+'<='
+'='
+null
+'~'
+'('
+')'
+null
+null
+null
+null
+null
+null
+
+token symbolic names:
+null
+AND
+OR
+NOT
+TRUE
+FALSE
+GT
+GE
+LT
+LE
+EQ
+NE
+RE
+LPAREN
+RPAREN
+DECIMAL
+VARIABLE
+QTEXT
+DQTEXT
+TEXT
+WS
+
+rule names:
+AND
+OR
+NOT
+TRUE
+FALSE
+GT
+GE
+LT
+LE
+EQ
+NE
+RE
+LPAREN
+RPAREN
+DECIMAL
+VARIABLE
+QTEXT
+DQTEXT
+TEXT
+WS
+
+channel names:
+DEFAULT_TOKEN_CHANNEL
+HIDDEN
+
+mode names:
+DEFAULT_MODE
+
+atn:
+[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 22, 136, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 5, 16, 83, 10, 16, 3, 16, 6, 16, 86, 10, 16, 13, 16, 14, 16, 87, 3, 16, 3, 16, 6, 16, 92, 10, 16, 13, 16, 14, 16, 93, 5, 16, 96, 10, 16, 3, 17, 3, 17, 7, 17, 100, 10, 17, 12, 17, 14, 17, 103, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 7, 18, 109, 10, 18, 12, 18, 14, 18, 112, 11, 18, 3, 18, 3, 18, 3, 19, 3, 19, 7, 19, 118, 10, 19, 12, 19, 14, 19, 121, 11, 19, 3, 19, 3, 19, 3, 20, 6, 20, 126, 10, 20, 13, 20, 14, 20, 127, 3, 21, 6, 21, 131, 10, 21, 13, 21, 14, 21, 132, 3, 21, 3, 21, 4, 110, 119, 2, 22, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 3, 2, 9, 4, 2, 35, 35, 96, 96, 3, 2, 50, 59, 8, 2, 37, 38, 50, 59, 67, 92, 97, 97, 99, 124, 128, 128, 3, 2, 41, 41, 3, 2, 36, 36, 7, 2, 46, 46, 50, 59, 67, 92, 97, 97, 99, 124, 5, 2, 11, 12, 14, 15, 34, 34, 2, 144, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 3, 43, 3, 2, 2, 2, 5, 45, 3, 2, 2, 2, 7, 47, 3, 2, 2, 2, 9, 50, 3, 2, 2, 2, 11, 55, 3, 2, 2, 2, 13, 61, 3, 2, 2, 2, 15, 63, 3, 2, 2, 2, 17, 66, 3, 2, 2, 2, 19, 68, 3, 2, 2, 2, 21, 71, 3, 2, 2, 2, 23, 73, 3, 2, 2, 2, 25, 75, 3, 2, 2, 2, 27, 77, 3, 2, 2, 2, 29, 79, 3, 2, 2, 2, 31, 82, 3, 2, 2, 2, 33, 97, 3, 2, 2, 2, 35, 106, 3, 2, 2, 2, 37, 115, 3, 2, 2, 2, 39, 125, 3, 2, 2, 2, 41, 130, 3, 2, 2, 2, 43, 44, 7, 40, 2, 2, 44, 4, 3, 2, 2, 2, 45, 46, 7, 126, 2, 2, 46, 6, 3, 2, 2, 2, 47, 48, 7, 38, 2, 2, 48, 49, 7, 35, 2, 2, 49, 8, 3, 2, 2, 2, 50, 51, 7, 118, 2, 2, 51, 52, 7, 116, 2, 2, 52, 53, 7, 119, 2, 2, 53, 54, 7, 103, 2, 2, 54, 10, 3, 2, 2, 2, 55, 56, 7, 104, 2, 2, 56, 57, 7, 99, 2, 2, 57, 58, 7, 110, 2, 2, 58, 59, 7, 117, 2, 2, 59, 60, 7, 103, 2, 2, 60, 12, 3, 2, 2, 2, 61, 62, 7, 64, 2, 2, 62, 14, 3, 2, 2, 2, 63, 64, 7, 64, 2, 2, 64, 65, 7, 63, 2, 2, 65, 16, 3, 2, 2, 2, 66, 67, 7, 62, 2, 2, 67, 18, 3, 2, 2, 2, 68, 69, 7, 62, 2, 2, 69, 70, 7, 63, 2, 2, 70, 20, 3, 2, 2, 2, 71, 72, 7, 63, 2, 2, 72, 22, 3, 2, 2, 2, 73, 74, 9, 2, 2, 2, 74, 24, 3, 2, 2, 2, 75, 76, 7, 128, 2, 2, 76, 26, 3, 2, 2, 2, 77, 78, 7, 42, 2, 2, 78, 28, 3, 2, 2, 2, 79, 80, 7, 43, 2, 2, 80, 30, 3, 2, 2, 2, 81, 83, 7, 47, 2, 2, 82, 81, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 85, 3, 2, 2, 2, 84, 86, 9, 3, 2, 2, 85, 84, 3, 2, 2, 2, 86, 87, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 95, 3, 2, 2, 2, 89, 91, 7, 48, 2, 2, 90, 92, 9, 3, 2, 2, 91, 90, 3, 2, 2, 2, 92, 93, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 96, 3, 2, 2, 2, 95, 89, 3, 2, 2, 2, 95, 96, 3, 2, 2, 2, 96, 32, 3, 2, 2, 2, 97, 101, 7, 66, 2, 2, 98, 100, 9, 4, 2, 2, 99, 98, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2, 2, 2, 101, 102, 3, 2, 2, 2, 102, 104, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2, 104, 105, 7, 66, 2, 2, 105, 34, 3, 2, 2, 2, 106, 110, 9, 5, 2, 2, 107, 109, 11, 2, 2, 2, 108, 107, 3, 2, 2, 2, 109, 112, 3, 2, 2, 2, 110, 111, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 111, 113, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 113, 114, 9, 5, 2, 2, 114, 36, 3, 2, 2, 2, 115, 119, 9, 6, 2, 2, 116, 118, 11, 2, 2, 2, 117, 116, 3, 2, 2, 2, 118, 121, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 120, 122, 3, 2, 2, 2, 121, 119, 3, 2, 2, 2, 122, 123, 9, 6, 2, 2, 123, 38, 3, 2, 2, 2, 124, 126, 9, 7, 2, 2, 125, 124, 3, 2, 2, 2, 126, 127, 3, 2, 2, 2, 127, 125, 3, 2, 2, 2, 127, 128, 3, 2, 2, 2, 128, 40, 3, 2, 2, 2, 129, 131, 9, 8, 2, 2, 130, 129, 3, 2, 2, 2, 131, 132, 3, 2, 2, 2, 132, 130, 3, 2, 2, 2, 132, 133, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 135, 8, 21, 2, 2, 135, 42, 3, 2, 2, 2, 12, 2, 82, 87, 93, 95, 101, 110, 119, 127, 132, 3, 8, 2, 2]
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.java b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.java
new file mode 100644
index 0000000000..0b890e4c03
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.java
@@ -0,0 +1,111 @@
+// Generated from SimpleBoolean.g4 by ANTLR 4.4
+
+ package org.idempiere.expression.logic;
+
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class SimpleBooleanLexer extends Lexer {
+ static { RuntimeMetaData.checkVersion("4.4", RuntimeMetaData.VERSION); }
+
+ protected static final DFA[] _decisionToDFA;
+ protected static final PredictionContextCache _sharedContextCache =
+ new PredictionContextCache();
+ public static final int
+ AND=1, OR=2, NOT=3, TRUE=4, FALSE=5, GT=6, GE=7, LT=8, LE=9, EQ=10, NE=11,
+ RE=12, LPAREN=13, RPAREN=14, DECIMAL=15, VARIABLE=16, QTEXT=17, DQTEXT=18,
+ TEXT=19, WS=20;
+ public static String[] modeNames = {
+ "DEFAULT_MODE"
+ };
+
+ public static final String[] tokenNames = {
+ "'\\u0000'", "'\\u0001'", "'\\u0002'", "'\\u0003'", "'\\u0004'", "'\\u0005'",
+ "'\\u0006'", "'\\u0007'", "'\b'", "'\t'", "'\n'", "'\\u000B'", "'\f'",
+ "'\r'", "'\\u000E'", "'\\u000F'", "'\\u0010'", "'\\u0011'", "'\\u0012'",
+ "'\\u0013'", "'\\u0014'"
+ };
+ public static final String[] ruleNames = {
+ "AND", "OR", "NOT", "TRUE", "FALSE", "GT", "GE", "LT", "LE", "EQ", "NE",
+ "RE", "LPAREN", "RPAREN", "DECIMAL", "VARIABLE", "QTEXT", "DQTEXT", "TEXT",
+ "WS"
+ };
+
+
+ public SimpleBooleanLexer(CharStream input) {
+ super(input);
+ _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+ }
+
+ @Override
+ public String getGrammarFileName() { return "SimpleBoolean.g4"; }
+
+ @Override
+ public String[] getTokenNames() { return tokenNames; }
+
+ @Override
+ public String[] getRuleNames() { return ruleNames; }
+
+ @Override
+ public String getSerializedATN() { return _serializedATN; }
+
+ @Override
+ public String[] getModeNames() { return modeNames; }
+
+ @Override
+ public ATN getATN() { return _ATN; }
+
+ public static final String _serializedATN =
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\26\u0088\b\1\4\2"+
+ "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
+ "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
+ "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\5\3"+
+ "\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\b\3\t\3\t\3\n"+
+ "\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\5\20S\n\20"+
+ "\3\20\6\20V\n\20\r\20\16\20W\3\20\3\20\6\20\\\n\20\r\20\16\20]\5\20`\n"+
+ "\20\3\21\3\21\7\21d\n\21\f\21\16\21g\13\21\3\21\3\21\3\22\3\22\7\22m\n"+
+ "\22\f\22\16\22p\13\22\3\22\3\22\3\23\3\23\7\23v\n\23\f\23\16\23y\13\23"+
+ "\3\23\3\23\3\24\6\24~\n\24\r\24\16\24\177\3\25\6\25\u0083\n\25\r\25\16"+
+ "\25\u0084\3\25\3\25\5enw\2\26\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13"+
+ "\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26\3\2\b\4\2##``"+
+ "\3\2\62;\3\2))\3\2$$\7\2..\62;C\\aac|\5\2\13\f\16\17\"\"\u0090\2\3\3\2"+
+ "\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17"+
+ "\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2"+
+ "\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3"+
+ "\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\3+\3\2\2\2\5-\3\2\2\2\7/\3\2\2\2\t\62\3"+
+ "\2\2\2\13\67\3\2\2\2\r=\3\2\2\2\17?\3\2\2\2\21B\3\2\2\2\23D\3\2\2\2\25"+
+ "G\3\2\2\2\27I\3\2\2\2\31K\3\2\2\2\33M\3\2\2\2\35O\3\2\2\2\37R\3\2\2\2"+
+ "!a\3\2\2\2#j\3\2\2\2%s\3\2\2\2\'}\3\2\2\2)\u0082\3\2\2\2+,\7(\2\2,\4\3"+
+ "\2\2\2-.\7~\2\2.\6\3\2\2\2/\60\7&\2\2\60\61\7#\2\2\61\b\3\2\2\2\62\63"+
+ "\7v\2\2\63\64\7t\2\2\64\65\7w\2\2\65\66\7g\2\2\66\n\3\2\2\2\678\7h\2\2"+
+ "89\7c\2\29:\7n\2\2:;\7u\2\2;<\7g\2\2<\f\3\2\2\2=>\7@\2\2>\16\3\2\2\2?"+
+ "@\7@\2\2@A\7?\2\2A\20\3\2\2\2BC\7>\2\2C\22\3\2\2\2DE\7>\2\2EF\7?\2\2F"+
+ "\24\3\2\2\2GH\7?\2\2H\26\3\2\2\2IJ\t\2\2\2J\30\3\2\2\2KL\7\u0080\2\2L"+
+ "\32\3\2\2\2MN\7*\2\2N\34\3\2\2\2OP\7+\2\2P\36\3\2\2\2QS\7/\2\2RQ\3\2\2"+
+ "\2RS\3\2\2\2SU\3\2\2\2TV\t\3\2\2UT\3\2\2\2VW\3\2\2\2WU\3\2\2\2WX\3\2\2"+
+ "\2X_\3\2\2\2Y[\7\60\2\2Z\\\t\3\2\2[Z\3\2\2\2\\]\3\2\2\2][\3\2\2\2]^\3"+
+ "\2\2\2^`\3\2\2\2_Y\3\2\2\2_`\3\2\2\2` \3\2\2\2ae\7B\2\2bd\13\2\2\2cb\3"+
+ "\2\2\2dg\3\2\2\2ef\3\2\2\2ec\3\2\2\2fh\3\2\2\2ge\3\2\2\2hi\7B\2\2i\"\3"+
+ "\2\2\2jn\t\4\2\2km\13\2\2\2lk\3\2\2\2mp\3\2\2\2no\3\2\2\2nl\3\2\2\2oq"+
+ "\3\2\2\2pn\3\2\2\2qr\t\4\2\2r$\3\2\2\2sw\t\5\2\2tv\13\2\2\2ut\3\2\2\2"+
+ "vy\3\2\2\2wx\3\2\2\2wu\3\2\2\2xz\3\2\2\2yw\3\2\2\2z{\t\5\2\2{&\3\2\2\2"+
+ "|~\t\6\2\2}|\3\2\2\2~\177\3\2\2\2\177}\3\2\2\2\177\u0080\3\2\2\2\u0080"+
+ "(\3\2\2\2\u0081\u0083\t\7\2\2\u0082\u0081\3\2\2\2\u0083\u0084\3\2\2\2"+
+ "\u0084\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085\u0086\3\2\2\2\u0086\u0087"+
+ "\b\25\2\2\u0087*\3\2\2\2\f\2RW]_enw\177\u0084\3\b\2\2";
+ public static final ATN _ATN =
+ new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+ static {
+ _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+ for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+ _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.tokens b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.tokens
new file mode 100644
index 0000000000..afffaf07f1
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanLexer.tokens
@@ -0,0 +1,33 @@
+QTEXT=17
+OR=2
+LT=8
+LPAREN=13
+TRUE=4
+DECIMAL=15
+TEXT=19
+RPAREN=14
+EQ=10
+GT=6
+NOT=3
+RE=12
+VARIABLE=16
+AND=1
+NE=11
+LE=9
+FALSE=5
+DQTEXT=18
+WS=20
+GE=7
+'false'=5
+')'=14
+'('=13
+'&'=1
+'<='=9
+'>'=6
+'~'=12
+'$!'=3
+'='=10
+'|'=2
+'<'=8
+'>='=7
+'true'=4
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanParser.java b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanParser.java
new file mode 100644
index 0000000000..e8b4573559
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanParser.java
@@ -0,0 +1,530 @@
+// Generated from SimpleBoolean.g4 by ANTLR 4.4
+
+ package org.idempiere.expression.logic;
+
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.misc.*;
+import org.antlr.v4.runtime.tree.*;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class SimpleBooleanParser extends Parser {
+ static { RuntimeMetaData.checkVersion("4.4", RuntimeMetaData.VERSION); }
+
+ protected static final DFA[] _decisionToDFA;
+ protected static final PredictionContextCache _sharedContextCache =
+ new PredictionContextCache();
+ public static final int
+ AND=1, OR=2, NOT=3, TRUE=4, FALSE=5, GT=6, GE=7, LT=8, LE=9, EQ=10, NE=11,
+ RE=12, LPAREN=13, RPAREN=14, DECIMAL=15, VARIABLE=16, QTEXT=17, DQTEXT=18,
+ TEXT=19, WS=20;
+ public static final String[] tokenNames = {
+ "", "'&'", "'|'", "'$!'", "'true'", "'false'", "'>'", "'>='",
+ "'<'", "'<='", "'='", "NE", "'~'", "'('", "')'", "DECIMAL", "VARIABLE",
+ "QTEXT", "DQTEXT", "TEXT", "WS"
+ };
+ public static final int
+ RULE_parse = 0, RULE_expression = 1, RULE_comparator = 2, RULE_binary = 3,
+ RULE_bool = 4;
+ public static final String[] ruleNames = {
+ "parse", "expression", "comparator", "binary", "bool"
+ };
+
+ @Override
+ public String getGrammarFileName() { return "SimpleBoolean.g4"; }
+
+ @Override
+ public String[] getTokenNames() { return tokenNames; }
+
+ @Override
+ public String[] getRuleNames() { return ruleNames; }
+
+ @Override
+ public String getSerializedATN() { return _serializedATN; }
+
+ @Override
+ public ATN getATN() { return _ATN; }
+
+ public SimpleBooleanParser(TokenStream input) {
+ super(input);
+ _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+ }
+ public static class ParseContext extends ParserRuleContext {
+ public TerminalNode EOF() { return getToken(SimpleBooleanParser.EOF, 0); }
+ public ExpressionContext expression() {
+ return getRuleContext(ExpressionContext.class,0);
+ }
+ public ParseContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_parse; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitParse(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final ParseContext parse() throws RecognitionException {
+ ParseContext _localctx = new ParseContext(_ctx, getState());
+ enterRule(_localctx, 0, RULE_parse);
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(10); expression(0);
+ setState(11); match(EOF);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class ExpressionContext extends ParserRuleContext {
+ public ExpressionContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_expression; }
+
+ public ExpressionContext() { }
+ public void copyFrom(ExpressionContext ctx) {
+ super.copyFrom(ctx);
+ }
+ }
+ public static class BinaryExpressionContext extends ExpressionContext {
+ public ExpressionContext left;
+ public BinaryContext op;
+ public ExpressionContext right;
+ public BinaryContext binary() {
+ return getRuleContext(BinaryContext.class,0);
+ }
+ public ExpressionContext expression(int i) {
+ return getRuleContext(ExpressionContext.class,i);
+ }
+ public List expression() {
+ return getRuleContexts(ExpressionContext.class);
+ }
+ public BinaryExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitBinaryExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class DecimalExpressionContext extends ExpressionContext {
+ public TerminalNode DECIMAL() { return getToken(SimpleBooleanParser.DECIMAL, 0); }
+ public DecimalExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitDecimalExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class BoolExpressionContext extends ExpressionContext {
+ public BoolContext bool() {
+ return getRuleContext(BoolContext.class,0);
+ }
+ public BoolExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitBoolExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class ContextVariablesContext extends ExpressionContext {
+ public TerminalNode VARIABLE() { return getToken(SimpleBooleanParser.VARIABLE, 0); }
+ public ContextVariablesContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitContextVariables(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class NotExpressionContext extends ExpressionContext {
+ public TerminalNode NOT() { return getToken(SimpleBooleanParser.NOT, 0); }
+ public ExpressionContext expression() {
+ return getRuleContext(ExpressionContext.class,0);
+ }
+ public NotExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitNotExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class ParenExpressionContext extends ExpressionContext {
+ public TerminalNode LPAREN() { return getToken(SimpleBooleanParser.LPAREN, 0); }
+ public TerminalNode RPAREN() { return getToken(SimpleBooleanParser.RPAREN, 0); }
+ public ExpressionContext expression() {
+ return getRuleContext(ExpressionContext.class,0);
+ }
+ public ParenExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitParenExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class TextContext extends ExpressionContext {
+ public TerminalNode TEXT() { return getToken(SimpleBooleanParser.TEXT, 0); }
+ public TextContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitText(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class QuotedTextContext extends ExpressionContext {
+ public TerminalNode QTEXT() { return getToken(SimpleBooleanParser.QTEXT, 0); }
+ public QuotedTextContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitQuotedText(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class DoubleQuotedTextContext extends ExpressionContext {
+ public TerminalNode DQTEXT() { return getToken(SimpleBooleanParser.DQTEXT, 0); }
+ public DoubleQuotedTextContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitDoubleQuotedText(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+ public static class ComparatorExpressionContext extends ExpressionContext {
+ public ExpressionContext left;
+ public ComparatorContext op;
+ public ExpressionContext right;
+ public ComparatorContext comparator() {
+ return getRuleContext(ComparatorContext.class,0);
+ }
+ public ExpressionContext expression(int i) {
+ return getRuleContext(ExpressionContext.class,i);
+ }
+ public List expression() {
+ return getRuleContexts(ExpressionContext.class);
+ }
+ public ComparatorExpressionContext(ExpressionContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitComparatorExpression(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final ExpressionContext expression() throws RecognitionException {
+ return expression(0);
+ }
+
+ private ExpressionContext expression(int _p) throws RecognitionException {
+ ParserRuleContext _parentctx = _ctx;
+ int _parentState = getState();
+ ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState);
+ ExpressionContext _prevctx = _localctx;
+ int _startState = 2;
+ enterRecursionRule(_localctx, 2, RULE_expression, _p);
+ try {
+ int _alt;
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(26);
+ switch (_input.LA(1)) {
+ case NOT:
+ {
+ _localctx = new NotExpressionContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+
+ setState(14); match(NOT);
+ setState(15); expression(9);
+ }
+ break;
+ case LPAREN:
+ {
+ _localctx = new ParenExpressionContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(16); match(LPAREN);
+ setState(17); expression(0);
+ setState(18); match(RPAREN);
+ }
+ break;
+ case TRUE:
+ case FALSE:
+ {
+ _localctx = new BoolExpressionContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(20); bool();
+ }
+ break;
+ case VARIABLE:
+ {
+ _localctx = new ContextVariablesContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(21); match(VARIABLE);
+ }
+ break;
+ case QTEXT:
+ {
+ _localctx = new QuotedTextContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(22); match(QTEXT);
+ }
+ break;
+ case DQTEXT:
+ {
+ _localctx = new DoubleQuotedTextContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(23); match(DQTEXT);
+ }
+ break;
+ case TEXT:
+ {
+ _localctx = new TextContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(24); match(TEXT);
+ }
+ break;
+ case DECIMAL:
+ {
+ _localctx = new DecimalExpressionContext(_localctx);
+ _ctx = _localctx;
+ _prevctx = _localctx;
+ setState(25); match(DECIMAL);
+ }
+ break;
+ default:
+ throw new NoViableAltException(this);
+ }
+ _ctx.stop = _input.LT(-1);
+ setState(38);
+ _errHandler.sync(this);
+ _alt = getInterpreter().adaptivePredict(_input,2,_ctx);
+ while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+ if ( _alt==1 ) {
+ if ( _parseListeners!=null ) triggerExitRuleEvent();
+ _prevctx = _localctx;
+ {
+ setState(36);
+ switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) {
+ case 1:
+ {
+ _localctx = new ComparatorExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((ComparatorExpressionContext)_localctx).left = _prevctx;
+ pushNewRecursionContext(_localctx, _startState, RULE_expression);
+ setState(28);
+ if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
+ setState(29); ((ComparatorExpressionContext)_localctx).op = comparator();
+ setState(30); ((ComparatorExpressionContext)_localctx).right = expression(9);
+ }
+ break;
+ case 2:
+ {
+ _localctx = new BinaryExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((BinaryExpressionContext)_localctx).left = _prevctx;
+ pushNewRecursionContext(_localctx, _startState, RULE_expression);
+ setState(32);
+ if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
+ setState(33); ((BinaryExpressionContext)_localctx).op = binary();
+ setState(34); ((BinaryExpressionContext)_localctx).right = expression(8);
+ }
+ break;
+ }
+ }
+ }
+ setState(40);
+ _errHandler.sync(this);
+ _alt = getInterpreter().adaptivePredict(_input,2,_ctx);
+ }
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ unrollRecursionContexts(_parentctx);
+ }
+ return _localctx;
+ }
+
+ public static class ComparatorContext extends ParserRuleContext {
+ public TerminalNode RE() { return getToken(SimpleBooleanParser.RE, 0); }
+ public TerminalNode GE() { return getToken(SimpleBooleanParser.GE, 0); }
+ public TerminalNode LT() { return getToken(SimpleBooleanParser.LT, 0); }
+ public TerminalNode GT() { return getToken(SimpleBooleanParser.GT, 0); }
+ public TerminalNode LE() { return getToken(SimpleBooleanParser.LE, 0); }
+ public TerminalNode EQ() { return getToken(SimpleBooleanParser.EQ, 0); }
+ public TerminalNode NE() { return getToken(SimpleBooleanParser.NE, 0); }
+ public ComparatorContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_comparator; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitComparator(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final ComparatorContext comparator() throws RecognitionException {
+ ComparatorContext _localctx = new ComparatorContext(_ctx, getState());
+ enterRule(_localctx, 4, RULE_comparator);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(41);
+ _la = _input.LA(1);
+ if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << GT) | (1L << GE) | (1L << LT) | (1L << LE) | (1L << EQ) | (1L << NE) | (1L << RE))) != 0)) ) {
+ _errHandler.recoverInline(this);
+ }
+ consume();
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class BinaryContext extends ParserRuleContext {
+ public TerminalNode AND() { return getToken(SimpleBooleanParser.AND, 0); }
+ public TerminalNode OR() { return getToken(SimpleBooleanParser.OR, 0); }
+ public BinaryContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_binary; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitBinary(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final BinaryContext binary() throws RecognitionException {
+ BinaryContext _localctx = new BinaryContext(_ctx, getState());
+ enterRule(_localctx, 6, RULE_binary);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(43);
+ _la = _input.LA(1);
+ if ( !(_la==AND || _la==OR) ) {
+ _errHandler.recoverInline(this);
+ }
+ consume();
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class BoolContext extends ParserRuleContext {
+ public TerminalNode FALSE() { return getToken(SimpleBooleanParser.FALSE, 0); }
+ public TerminalNode TRUE() { return getToken(SimpleBooleanParser.TRUE, 0); }
+ public BoolContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_bool; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof SimpleBooleanVisitor ) return ((SimpleBooleanVisitor extends T>)visitor).visitBool(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final BoolContext bool() throws RecognitionException {
+ BoolContext _localctx = new BoolContext(_ctx, getState());
+ enterRule(_localctx, 8, RULE_bool);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(45);
+ _la = _input.LA(1);
+ if ( !(_la==TRUE || _la==FALSE) ) {
+ _errHandler.recoverInline(this);
+ }
+ consume();
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
+ switch (ruleIndex) {
+ case 1: return expression_sempred((ExpressionContext)_localctx, predIndex);
+ }
+ return true;
+ }
+ private boolean expression_sempred(ExpressionContext _localctx, int predIndex) {
+ switch (predIndex) {
+ case 0: return precpred(_ctx, 8);
+ case 1: return precpred(_ctx, 7);
+ }
+ return true;
+ }
+
+ public static final String _serializedATN =
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\26\62\4\2\t\2\4\3"+
+ "\t\3\4\4\t\4\4\5\t\5\4\6\t\6\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+
+ "\3\3\3\3\3\3\3\3\3\3\3\5\3\35\n\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\7\3"+
+ "\'\n\3\f\3\16\3*\13\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\2\3\4\7\2\4\6\b\n\2"+
+ "\5\3\2\b\16\3\2\3\4\3\2\6\7\65\2\f\3\2\2\2\4\34\3\2\2\2\6+\3\2\2\2\b-"+
+ "\3\2\2\2\n/\3\2\2\2\f\r\5\4\3\2\r\16\7\2\2\3\16\3\3\2\2\2\17\20\b\3\1"+
+ "\2\20\21\7\5\2\2\21\35\5\4\3\13\22\23\7\17\2\2\23\24\5\4\3\2\24\25\7\20"+
+ "\2\2\25\35\3\2\2\2\26\35\5\n\6\2\27\35\7\22\2\2\30\35\7\23\2\2\31\35\7"+
+ "\24\2\2\32\35\7\25\2\2\33\35\7\21\2\2\34\17\3\2\2\2\34\22\3\2\2\2\34\26"+
+ "\3\2\2\2\34\27\3\2\2\2\34\30\3\2\2\2\34\31\3\2\2\2\34\32\3\2\2\2\34\33"+
+ "\3\2\2\2\35(\3\2\2\2\36\37\f\n\2\2\37 \5\6\4\2 !\5\4\3\13!\'\3\2\2\2\""+
+ "#\f\t\2\2#$\5\b\5\2$%\5\4\3\n%\'\3\2\2\2&\36\3\2\2\2&\"\3\2\2\2\'*\3\2"+
+ "\2\2(&\3\2\2\2()\3\2\2\2)\5\3\2\2\2*(\3\2\2\2+,\t\2\2\2,\7\3\2\2\2-.\t"+
+ "\3\2\2.\t\3\2\2\2/\60\t\4\2\2\60\13\3\2\2\2\5\34&(";
+ public static final ATN _ATN =
+ new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+ static {
+ _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+ for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+ _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanVisitor.java b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanVisitor.java
new file mode 100644
index 0000000000..66ec9de122
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/SimpleBooleanVisitor.java
@@ -0,0 +1,110 @@
+// Generated from SimpleBoolean.g4 by ANTLR 4.4
+
+ package org.idempiere.expression.logic;
+
+import org.antlr.v4.runtime.misc.NotNull;
+import org.antlr.v4.runtime.tree.ParseTreeVisitor;
+
+/**
+ * This interface defines a complete generic visitor for a parse tree produced
+ * by {@link SimpleBooleanParser}.
+ *
+ * @param The return type of the visit operation. Use {@link Void} for
+ * operations with no return type.
+ */
+public interface SimpleBooleanVisitor extends ParseTreeVisitor {
+ /**
+ * Visit a parse tree produced by the {@code boolExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitBoolExpression(@NotNull SimpleBooleanParser.BoolExpressionContext ctx);
+ /**
+ * Visit a parse tree produced by {@link SimpleBooleanParser#bool}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitBool(@NotNull SimpleBooleanParser.BoolContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code notExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitNotExpression(@NotNull SimpleBooleanParser.NotExpressionContext ctx);
+ /**
+ * Visit a parse tree produced by {@link SimpleBooleanParser#parse}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitParse(@NotNull SimpleBooleanParser.ParseContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code parenExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitParenExpression(@NotNull SimpleBooleanParser.ParenExpressionContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code doubleQuotedText}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitDoubleQuotedText(@NotNull SimpleBooleanParser.DoubleQuotedTextContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code binaryExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitBinaryExpression(@NotNull SimpleBooleanParser.BinaryExpressionContext ctx);
+ /**
+ * Visit a parse tree produced by {@link SimpleBooleanParser#comparator}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitComparator(@NotNull SimpleBooleanParser.ComparatorContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code decimalExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitDecimalExpression(@NotNull SimpleBooleanParser.DecimalExpressionContext ctx);
+ /**
+ * Visit a parse tree produced by {@link SimpleBooleanParser#binary}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitBinary(@NotNull SimpleBooleanParser.BinaryContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code contextVariables}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitContextVariables(@NotNull SimpleBooleanParser.ContextVariablesContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code text}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitText(@NotNull SimpleBooleanParser.TextContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code quotedText}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitQuotedText(@NotNull SimpleBooleanParser.QuotedTextContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code comparatorExpression}
+ * labeled alternative in {@link SimpleBooleanParser#expression}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitComparatorExpression(@NotNull SimpleBooleanParser.ComparatorExpressionContext ctx);
+}
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/idempiere/expression/logic/ThrowingErrorListener.java b/org.adempiere.base/src/org/idempiere/expression/logic/ThrowingErrorListener.java
new file mode 100644
index 0000000000..fa687a17c0
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/expression/logic/ThrowingErrorListener.java
@@ -0,0 +1,46 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.expression.logic;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class ThrowingErrorListener extends BaseErrorListener {
+
+ public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();
+
+ @Override
+ public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
+ String msg, RecognitionException e) throws ParseCancellationException {
+ throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg);
+ }
+}
diff --git a/org.adempiere.install/install.app.launch b/org.adempiere.install/install.app.launch
index 1dbc74c1c8..d54a26ae63 100644
--- a/org.adempiere.install/install.app.launch
+++ b/org.adempiere.install/install.app.launch
@@ -48,6 +48,7 @@
+
diff --git a/org.adempiere.install/install.console.app.launch b/org.adempiere.install/install.console.app.launch
index 187975d213..4c6f61d8dd 100644
--- a/org.adempiere.install/install.console.app.launch
+++ b/org.adempiere.install/install.console.app.launch
@@ -48,6 +48,7 @@
+
diff --git a/org.adempiere.install/install.silent.app.launch b/org.adempiere.install/install.silent.app.launch
index 29eb37d1a5..4b48c83d88 100644
--- a/org.adempiere.install/install.silent.app.launch
+++ b/org.adempiere.install/install.silent.app.launch
@@ -48,6 +48,7 @@
+
diff --git a/org.adempiere.server-feature/feature.xml b/org.adempiere.server-feature/feature.xml
index abd8dc62ed..094a933e70 100644
--- a/org.adempiere.server-feature/feature.xml
+++ b/org.adempiere.server-feature/feature.xml
@@ -560,4 +560,25 @@
fragment="true"
unpack="false"/>
+
+
+
+
+
+
diff --git a/org.adempiere.server-feature/server.product.functionaltest.launch b/org.adempiere.server-feature/server.product.functionaltest.launch
index b5f16f0f3b..c292c4aa5f 100644
--- a/org.adempiere.server-feature/server.product.functionaltest.launch
+++ b/org.adempiere.server-feature/server.product.functionaltest.launch
@@ -145,6 +145,7 @@
+
diff --git a/org.adempiere.server-feature/server.product.launch b/org.adempiere.server-feature/server.product.launch
index 5accbcf01e..1e5552d179 100644
--- a/org.adempiere.server-feature/server.product.launch
+++ b/org.adempiere.server-feature/server.product.launch
@@ -145,6 +145,7 @@
+
diff --git a/org.adempiere.server-feature/setup/configuration/config.ini b/org.adempiere.server-feature/setup/configuration/config.ini
index 0c5aeb0b37..62e2aabb29 100644
--- a/org.adempiere.server-feature/setup/configuration/config.ini
+++ b/org.adempiere.server-feature/setup/configuration/config.ini
@@ -81,7 +81,8 @@ osgi.bundles=org.eclipse.equinox.ds@1:start,\
org.eclipse.osgi@start,\
org.dom4j,\
wrapped.com.google.zxing.javase,\
- wrapped.dev.samstevens.totp.totp
+ wrapped.dev.samstevens.totp.totp,\
+ org.antlr.antlr4-runtime
osgi.framework.extensions=
osgi.bundles.defaultStartLevel=4
osgi.compatibility.bootdelegation=true
diff --git a/org.idempiere.p2.targetplatform/maven.locations.xml b/org.idempiere.p2.targetplatform/maven.locations.xml
index 045a1c155d..1f9facf9f9 100644
--- a/org.idempiere.p2.targetplatform/maven.locations.xml
+++ b/org.idempiere.p2.targetplatform/maven.locations.xml
@@ -176,5 +176,11 @@
3.4.1
jar
+
+ org.antlr
+ antlr4-runtime
+ 4.9.2
+
diff --git a/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target b/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
index cde3a1b7b0..f74d2ed20b 100644
--- a/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
+++ b/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
@@ -465,19 +465,22 @@
1.1.0.Final
jar
-
- dev.samstevens.totp
- totp
- 1.7.1
- jar
+
+ dev.samstevens.totp
+ totp
+ 1.7.1
+ jar
-
- com.google.zxing
- javase
- 3.4.1
- jar
+
+ com.google.zxing
+ javase
+ 3.4.1
+ jar
+
+
+ org.antlr
+ antlr4-runtime
+ 4.9.2
diff --git a/org.idempiere.test/idempiere.unit.test.launch b/org.idempiere.test/idempiere.unit.test.launch
index f68b2b4c19..5ba01e10f8 100644
--- a/org.idempiere.test/idempiere.unit.test.launch
+++ b/org.idempiere.test/idempiere.unit.test.launch
@@ -108,6 +108,7 @@
+
diff --git a/org.idempiere.test/src/org/idempiere/test/base/LogicExpressionTest.java b/org.idempiere.test/src/org/idempiere/test/base/LogicExpressionTest.java
new file mode 100644
index 0000000000..568270d2a7
--- /dev/null
+++ b/org.idempiere.test/src/org/idempiere/test/base/LogicExpressionTest.java
@@ -0,0 +1,450 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.test.base;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.compiere.util.Env;
+import org.compiere.util.Evaluatee;
+import org.compiere.util.LegacyLogicEvaluator;
+import org.idempiere.expression.logic.LogicEvaluator;
+import org.idempiere.test.AbstractTestCase;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("deprecation")
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class LogicExpressionTest extends AbstractTestCase {
+
+ private final static ContextEvaluatee evaluatee = new ContextEvaluatee();
+
+ public LogicExpressionTest() {
+ }
+
+ @Test
+ public void testEqual() {
+
+ String expr = "@$Element_AY@='Y'";
+ Env.setContext(Env.getCtx(), "$Element_AY", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "Y");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "N");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "$Element_AY", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ expr = "@$Element_AY@=Y";
+ Env.setContext(Env.getCtx(), "$Element_AY", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "Y");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "N");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "$Element_AY", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_AY", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testAnd() {
+ String expr = "@$Element_BP@=Y & @AnyBPartner@=N";
+ Env.setContext(Env.getCtx(), "$Element_BP", (String)null);
+ Env.setContext(Env.getCtx(), "AnyBPartner", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_BP", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "AnyBPartner", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "AnyBPartner", "N");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_BP", "N");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "$Element_BP", (String)null);
+ Env.setContext(Env.getCtx(), "AnyBPartner", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_BP", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "AnyBPartner", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "AnyBPartner", "N");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "$Element_BP", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testIn() {
+ String expr = "@LineType@=C&@CalculationType@=A,R,S";
+ Env.setContext(Env.getCtx(), "LineType", (String)null);
+ Env.setContext(Env.getCtx(), "CalculationType", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "LineType", "C");
+ Env.setContext(Env.getCtx(), "CalculationType", "B");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "A");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "R");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "S");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "LineType", "D");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "LineType", (String)null);
+ Env.setContext(Env.getCtx(), "CalculationType", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "LineType", "C");
+ Env.setContext(Env.getCtx(), "CalculationType", "B");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "A");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "R");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "CalculationType", "S");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "LineType", "D");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testNotEqual() {
+ String expr = "@C_Bpartner_ID@!0";
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", "0");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", "100");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", "0");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Bpartner_ID", "100");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ expr = "@IsOverUnderPayment@=Y & @C_Invoice_ID@^0";
+ Env.setContext(Env.getCtx(), "IsOverUnderPayment", (String)null);
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsOverUnderPayment", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", "0");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", "100");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "IsOverUnderPayment", (String)null);
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsOverUnderPayment", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", "0");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "C_Invoice_ID", "100");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testOrAnd() {
+ String expr = "@IsSold@='Y' | @IsPurchased@='Y' & @IsSummary@='N'";
+ Env.setContext(Env.getCtx(), "IsSold", (String)null);
+ Env.setContext(Env.getCtx(), "IsPurchased", (String)null);
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsPurchased", "Y");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "N");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "IsSold", (String)null);
+ Env.setContext(Env.getCtx(), "IsPurchased", (String)null);
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsPurchased", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "N");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testAndOr() {
+ String expr = "@IsSummary@='N' & @ProductType@=I | @ProductType@=S";
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "I");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "S");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "I");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "S");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testAndOrGroup() {
+ String expr = "@IsSummary@='N' & (@ProductType@=I | @ProductType@=S)";
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ Env.setContext(Env.getCtx(), "ProductType", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "I");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "ProductType", "S");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testOrAndGroup() {
+ String expr = "@IsSold@='Y' | (@IsPurchased@='Y' & @IsSummary@='N')";
+ Env.setContext(Env.getCtx(), "IsSold", (String)null);
+ Env.setContext(Env.getCtx(), "IsPurchased", (String)null);
+ Env.setContext(Env.getCtx(), "IsSummary", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "N");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsPurchased", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSold", "N");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSummary", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testGT() {
+ String expr = "@IsLot@=Y& @M_LotCtl_ID@ > 0";
+ Env.setContext(Env.getCtx(), "IsLot", (String)null);
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "0");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "101");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "N");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "IsLot", (String)null);
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "0");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "101");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "N");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testGE() {
+ String expr = "@IsLot@=Y& @M_LotCtl_ID@ >= 100";
+ Env.setContext(Env.getCtx(), "IsLot", (String)null);
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "0");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "100");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "99");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testLT() {
+ String expr = "@A_Asset_ID@<1&@A_CreateAsset@='Y'";
+ Env.setContext(Env.getCtx(), "A_Asset_ID", (String)null);
+ Env.setContext(Env.getCtx(), "A_CreateAsset", (String)null);
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "1");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_CreateAsset", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "0");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "A_Asset_ID", (String)null);
+ Env.setContext(Env.getCtx(), "A_CreateAsset", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "1");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_CreateAsset", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "0");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testLE() {
+ String expr = "@A_Asset_ID@<=1&@A_CreateAsset@='Y'";
+ Env.setContext(Env.getCtx(), "A_Asset_ID", (String)null);
+ Env.setContext(Env.getCtx(), "A_CreateAsset", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "2");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_CreateAsset", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "A_Asset_ID", "1");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testNegate() {
+ String expr = "$!(@IsLot@=Y & @M_LotCtl_ID@ > 0)";
+ Env.setContext(Env.getCtx(), "IsLot", (String)null);
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", (String)null);
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsLot", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "1");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "M_LotCtl_ID", "0");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testRE() {
+ String expr = "@Identifier@ ~ '^([a-zA-Z_$][a-zA-Z\\d_$]*)$'";
+ Env.setContext(Env.getCtx(), "Identifier", (String)null);
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "validIdentifier");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "$validIdentifier");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "~inValidIdentifier");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "_validIdentifier");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "0inValidIdentifier");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "Identifier", "validIdentifier0");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ @Test
+ public void testValidation() {
+ Exception ex = null;
+ String expr = "@IsSummary@='N' & (@ProductType@=I | @ProductType@=S)";
+ try {
+ LogicEvaluator.validate(expr);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNull(ex);
+ expr = expr.substring(0, expr.length()-1);
+ try {
+ LogicEvaluator.validate(expr);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+ System.out.println(ex.getMessage());
+ }
+
+ @Test
+ public void testConditionalVariable() {
+ String expr = "@IsSOTrx:N@=N | @+IgnoreIsSOTrxInBPInfo:N@=Y";
+ Env.setContext(Env.getCtx(), "IsSOTrx", (String)null);
+ Env.setContext(Env.getCtx(), "+IgnoreIsSOTrxInBPInfo", (String)null);
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSOTrx", "Y");
+ assertFalse(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "+IgnoreIsSOTrxInBPInfo", "Y");
+ assertTrue(LegacyLogicEvaluator.evaluateLogic(evaluatee, expr));
+
+ Env.setContext(Env.getCtx(), "IsSOTrx", (String)null);
+ Env.setContext(Env.getCtx(), "+IgnoreIsSOTrxInBPInfo", (String)null);
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "IsSOTrx", "Y");
+ assertFalse(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ Env.setContext(Env.getCtx(), "+IgnoreIsSOTrxInBPInfo", "Y");
+ assertTrue(LogicEvaluator.evaluateLogic(evaluatee, expr));
+ }
+
+ private static class ContextEvaluatee implements Evaluatee {
+
+ @Override
+ public String get_ValueAsString(String variableName) {
+ return Env.getContext(Env.getCtx(), variableName);
+ }
+
+ }
+}