TermExpressionParser { public static List<Term> parse(String expression) { Query<?, QueryParamEntity> conditional = QueryParamEntity.newQuery(); NestConditional<?> nest = null; char[] buf = new char[128]; byte len = 0; byte spaceLen = 0; char[] currentColumn = null; char[] currentValue = null; String currentTermType = null; String currentType = "and"; byte quotationMarks = 0; char[] all = expression.toCharArray(); for (char c : all) { if (c == '\'' || c == '"') { if (quotationMarks != 0) { quotationMarks = 0; continue; } quotationMarks++; continue; } else if (c == '(') { nest = (nest == null ? (currentType.equals("or") ? conditional.orNest() : conditional.nest()) : (currentType.equals("or") ? nest.orNest() : nest.nest())); len = 0; continue; } else if (c == ')') { if (nest == null) { continue; } if (null != currentColumn) { currentValue = Arrays.copyOf(buf, len); nest.accept(new String(currentColumn), convertTermType(currentTermType), new String(currentValue)); currentColumn = null; currentTermType = null; } Object end = nest.end(); nest = end instanceof NestConditional ? ((NestConditional) end) : null; len = 0; spaceLen++; continue; } else if (c == '=' || c == '>' || c == '<') { if (currentTermType != null) { currentTermType += String.valueOf(c); } else { currentTermType = String.valueOf(c); } if (currentColumn == null) { currentColumn = Arrays.copyOf(buf, len); } spaceLen++; len = 0; continue; } else if (c == ' ') { if (len == 0) { continue; } if (quotationMarks != 0) { buf[len++] = c; continue; } spaceLen++; if (currentColumn == null && (spaceLen == 1 || spaceLen % 5 == 0)) { currentColumn = Arrays.copyOf(buf, len); len = 0; continue; } if (null != currentColumn) { if (null == currentTermType) { currentTermType = new String(Arrays.copyOf(buf, len)); len = 0; continue; } currentValue = Arrays.copyOf(buf, len); if (nest != null) { nest.accept(new String(currentColumn), convertTermType(currentTermType), new String(currentValue)); } else { conditional.accept(new String(currentColumn), convertTermType(currentTermType), new String(currentValue)); } currentColumn = null; currentTermType = null; len = 0; continue; } else if (len == 2 || len == 3) { String type = new String(Arrays.copyOf(buf, len)); if (type.equalsIgnoreCase("or")) { currentType = "or"; if (nest != null) { nest.or(); } else { conditional.or(); } len = 0; continue; } else if (type.equalsIgnoreCase("and")) { currentType = "and"; if (nest != null) { nest.and(); } else { conditional.and(); } len = 0; continue; } else { currentColumn = Arrays.copyOf(buf, len); len = 0; spaceLen++; } } else { currentColumn = Arrays.copyOf(buf, len); len = 0; spaceLen++; } continue; } buf[len++] = c; } if (null != currentColumn) { currentValue = Arrays.copyOf(buf, len); if (nest != null) { nest.accept(new String(currentColumn), convertTermType(currentTermType), new String(currentValue)); } else { conditional.accept(new String(currentColumn), convertTermType(currentTermType), new String(currentValue)); } } return conditional.getParam().getTerms(); }  static List<Term> parse(String expression);  }
@Test public void testSimple() { String expression = "name=测试 or age=10"; List<Term> terms = TermExpressionParser.parse(expression); Assert.assertNotNull(terms); Assert.assertEquals(terms.size(), 2); Assert.assertEquals(terms.get(0).getColumn(), "name"); Assert.assertEquals(terms.get(0).getValue(), "测试"); Assert.assertEquals(terms.get(1).getColumn(), "age"); Assert.assertEquals(terms.get(1).getValue(), "10"); Assert.assertEquals(terms.get(1).getType(), Term.Type.or); }
@Test public void testNest() { String expression = "name = 测试 and (age > 10 or age <= 20) and test like test2 and (age gt age2 or age btw age3,age4 or (age > 10 or age <= 20))"; System.out.println(expression); List<Term> terms = TermExpressionParser.parse(expression); System.out.println(JSON.toJSONString(terms, SerializerFeature.PrettyFormat)); Assert.assertNotNull(terms); Assert.assertEquals(terms.size(), 4); Assert.assertEquals(terms.get(1).getTerms().size(),2); Assert.assertEquals(terms.get(0).getColumn(), "name"); Assert.assertEquals(terms.get(0).getValue(), "测试"); Assert.assertEquals(terms.get(1).getTerms().get(0).getColumn(), "age"); Assert.assertEquals(terms.get(1).getTerms().get(0).getTermType(), "gt"); Assert.assertEquals(terms.get(1).getTerms().get(0).getValue(), "10"); Assert.assertEquals(terms.get(1).getTerms().get(1).getColumn(), "age"); Assert.assertEquals(terms.get(1).getTerms().get(1).getTermType(), "lte"); Assert.assertEquals(terms.get(1).getTerms().get(1).getValue(), "20"); Assert.assertEquals(terms.get(1).getTerms().get(1).getType(), Term.Type.or); Assert.assertEquals(terms.get(2).getColumn(), "test"); Assert.assertEquals(terms.get(2).getValue(), "test2"); Assert.assertEquals(terms.get(2).getTermType(), "like"); }
@Test public void testDateSpace() { String expression = "(name=测试 or age=10) and (birth btw \"2019-07-26 12:00:00, 2019-08-04 12:00:00\" or startTime <= '2019-08-04 12:00:00') and finishTime >= '2019-08-01 00:00:00'"; List<Term> terms = TermExpressionParser.parse(expression); System.out.println(JSON.toJSONString(terms, SerializerFeature.PrettyFormat)); Assert.assertEquals(terms.size(), 3); Assert.assertEquals(terms.get(0).getTerms().size(), 2); Assert.assertEquals(terms.get(1).getTerms().get(0).getColumn(), "birth"); Assert.assertEquals(terms.get(1).getTerms().get(0).getTermType(), "btw"); Assert.assertEquals(terms.get(1).getTerms().get(0).getValue(), "2019-07-26 12:00:00, 2019-08-04 12:00:00"); Assert.assertEquals(terms.get(1).getTerms().get(1).getColumn(), "startTime"); Assert.assertEquals(terms.get(1).getTerms().get(1).getTermType(), "lte"); Assert.assertEquals(terms.get(1).getTerms().get(1).getValue(), "2019-08-04 12:00:00"); Assert.assertEquals(terms.get(1).getTerms().get(1).getType(), Term.Type.or); Assert.assertEquals(terms.get(2).getColumn(), "finishTime"); Assert.assertEquals(terms.get(2).getValue(), "2019-08-01 00:00:00"); Assert.assertEquals(terms.get(2).getTermType(), "gte"); }