org.meteoinfo.table.SQLExpression Maven / Gradle / Ivy
/* Copyright 2012 Yaqiang Wang,
* [email protected]
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library 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 Lesser
* General Public License for more details.
*/
package org.meteoinfo.table;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Map;
/**
*
* @author yaqiang
*/
public class SQLExpression {
//
private final String expression;
private final int exp_len;
private final char[] exp_array;
private final ArrayList token_list;
private boolean is_flushed;
private char c;
private StringBuffer sb;
private int cur_token_index;
private final int token_count;
//
//
public SQLExpression(String SQLExpression) {
this.expression = SQLExpression;
this.exp_len = SQLExpression.length();
this.exp_array = SQLExpression.toCharArray();
this.token_list = new ArrayList<>();
this.is_flushed = true;
this.cur_token_index = -1;
this.sb = new StringBuffer();
this.initTokenList();
this.token_count = this.token_list.size();
}
private void flush() {
if (this.is_flushed) {
return;
}
String token = this.sb.toString();
if (token.startsWith("\""))
token = token.substring(1);
if (token.endsWith("\""))
token = token.substring(0, token.length() - 1);
this.token_list.add(token);
this.sb = new StringBuffer();
this.is_flushed = true;
}
private void collect() {
this.sb.append(c);
this.is_flushed = false;
}
private boolean nextToken() {
if (this.cur_token_index < this.token_count - 1) {
this.cur_token_index++;
return true;
}
return false;
}
private String currentToken() {
return this.token_list.get(this.cur_token_index);
}
private void initTokenList() {
for (int i = 0; i < this.exp_len; i++) {
c = exp_array[i];
if (Character.isWhitespace(c)) {
if (!(this.sb.length() > 0 && this.sb.substring(0, 1).equals("\""))) {
this.flush();
continue;
}
}
switch (c) {
case '<':
this.flush();
if (i + 1 < this.exp_len && exp_array[i + 1] == '=') {
this.token_list.add("<=");
i++;
} else if (i + 1 < this.exp_len && exp_array[i + 1] == '>') {
this.token_list.add("<>");
i++;
} else {
this.token_list.add("<");
}
break;
case '>':
this.flush();
if (i + 1 < this.exp_len && exp_array[i + 1] == '=') {
this.token_list.add(">=");
i++;
} else {
this.token_list.add(">");
}
break;
case '(':
this.flush();
this.token_list.add("(");
break;
case ')':
this.flush();
this.token_list.add(")");
break;
case '=':
if (i + 1 < this.exp_len && exp_array[i + 1] == '=') {
this.flush();
//this.token_list.add("==");
i++;
} else {
this.collect();
}
break;
case '!':
if (i + 1 < this.exp_len && exp_array[i + 1] == '=') {
this.flush();
this.token_list.add("!=");
i++;
} else {
this.collect();
}
break;
case '"':
if (this.sb.length() > 0 && this.sb.substring(0, 1).equals("\"")){
this.flush();
} else {
this.collect();
}
break;
default:
this.collect();
break;
}
}
this.flush();
}
//
//
//
//
public boolean eval(Map dr) {
this.nextToken();
boolean result = this.doAndOr(dr);
this.cur_token_index = -1;
return result;
}
private boolean doAndOr(Map dr) {
boolean result = this.doNot(dr);
String op;
boolean result_right;
while ((op = this.currentToken()).equalsIgnoreCase("and") || op.equalsIgnoreCase("or")) {
this.nextToken();
if (op.equalsIgnoreCase("and")) {
result_right = this.doNot(dr);
result = result && result_right;
} else {
result_right = this.doNot(dr);
result = result || result_right;
}
}
return result;
}
private boolean doNot(Map dr) {
String op;
if ((op = this.currentToken()).equalsIgnoreCase("not")) {
this.nextToken();
}
boolean result = this.doBrackets(dr);
if (op.equalsIgnoreCase("not")) {
return !result;
}
return result;
}
private boolean doBrackets(Map dr) {
boolean result;
if (this.currentToken().equals("(")) {
this.nextToken();
result = this.doAndOr(dr);
this.nextToken();
} else {
result = this.doCompare(dr);
}
return result;
}
private boolean doCompare(Map dr) {
Object field = dr.get(this.currentToken().toLowerCase());
//Object field = this.currentToken();
this.nextToken();
String opt = this.currentToken();
this.nextToken();
String value = this.currentToken();
this.nextToken();
switch (opt) {
case "like":
return isLike(field, value);
case ">":
return isGreat(field, value);
case "<":
return isLess(field, value);
case "=":
return isEquals(field, value);
case ">=":
return isGreatEquals(field, value);
case "<=":
return isLessEquals(field, value);
case "<>":
return isNotEquals(field, value);
default:
break;
}
return false;
}
//
private static boolean isLike(Object field, String value) {
int len = value.length();
if (value.startsWith("'%") && value.endsWith("%'")) {
return Convert.toString(field).contains(value.substring(2, len - 2));
} else if (value.startsWith("'%")) {
return Convert.toString(field).endsWith(value.substring(2, len - 1));
} else if (value.endsWith("%'")) {
return Convert.toString(field).startsWith(value.substring(1, len - 2));
} else {
return Convert.toString(field).equals(value.substring(1, len - 1));
}
}
private static boolean isLess(Object field, String value) {
if (field instanceof Number) {
return Convert.toFloat(field) < Convert.toFloat(value);
}
if (field instanceof LocalDateTime) {
return ((LocalDateTime)field).isBefore(Convert.toDate(value));
}
return Convert.toString(field).compareTo(value.substring(1, value.length() - 1)) < 0;
}
private static boolean isGreat(Object field, String value) {
if (field instanceof Number) {
return Convert.toFloat(field) > Convert.toFloat(value);
}
if (field instanceof LocalDateTime) {
return ((LocalDateTime) field).isAfter(Convert.toDate(value));
}
return Convert.toString(field).compareTo(value.substring(1, value.length() - 1)) > 0;
}
private static boolean isEquals(Object field, String value) {
if (value.equals("null")) {
return field == null;
}
if (field instanceof Number) {
return Convert.toFloat(field) == Convert.toFloat(value);
}
if (field instanceof Boolean) {
return Convert.toBool(field) == Convert.toBool(value);
}
if (field instanceof LocalDateTime) {
return ((LocalDateTime)field).equals(Convert.toDate(value));
}
//return Convert.toString(field).equals(value.substring(1, value.length() - 1));
return Convert.toString(field).equals(value);
}
private static boolean isNotEquals(Object field, String value) {
if (value.equals("null")) {
return field != null;
}
if (field instanceof Number) {
return Convert.toFloat(field) != Convert.toFloat(value);
}
if (field instanceof Boolean) {
return Convert.toBool(field) != Convert.toBool(value);
}
if (field instanceof LocalDateTime) {
return !((LocalDateTime)field).equals(Convert.toDate(value));
}
//return !Convert.toString(field).equals(value.substring(1, value.length() - 1));
return !Convert.toString(field).equals(value);
}
private static boolean isLessEquals(Object field, String value) {
if (field instanceof Number) {
return Convert.toFloat(field) <= Convert.toFloat(value);
}
if (field instanceof LocalDateTime) {
return ((LocalDateTime)field).isBefore(Convert.toDate(value)) || ((LocalDateTime)field).equals(Convert.toDate(value));
}
return Convert.toString(field).compareTo(value.substring(1, value.length() - 1)) <= 0;
}
private static boolean isGreatEquals(Object field, String value) {
if (field instanceof Number) {
return Convert.toFloat(field) >= Convert.toFloat(value);
}
if (field instanceof LocalDateTime) {
return ((LocalDateTime)field).isAfter(Convert.toDate(value)) || ((LocalDateTime)field).equals(Convert.toDate(value));
}
return Convert.toString(field).compareTo(value.substring(1, value.length() - 1)) >= 0;
}
//
}
class Convert {
public static String toString(Object o) {
return toString(o, "");
}
public static String toString(Object o, String defValue) {
if (o == null) {
return defValue;
}
return o.toString();
}
public static int toInt(Object o) {
return toInt(o, 0);
}
public static int toInt(Object o, int defValue) {
if (o == null) {
return defValue;
}
if (o instanceof Integer) {
return (Integer) o;
}
try {
return (int) Float.parseFloat(o.toString());
} catch (Exception e) {
return defValue;
}
}
public static long toLong(Object o) {
if (o == null) {
return 0L;
}
if (o instanceof Long) {
return (Long) o;
}
try {
return Long.parseLong(o.toString());
} catch (Exception e) {
return 0L;
}
}
public static float toFloat(Object o) {
if (o == null) {
return 0F;
}
if (o instanceof Float) {
return (Float) o;
}
try {
return Float.parseFloat(o.toString());
} catch (Exception e) {
return 0F;
}
}
public static boolean toBool(Object o) {
if (o == null) {
return false;
}
if (o instanceof Boolean) {
return (Boolean) o;
}
try {
return Boolean.parseBoolean(o.toString());
} catch (Exception e) {
return false;
}
}
public static LocalDateTime toDate(Object o) {
return toDate(o, LocalDateTime.now());
}
public static LocalDateTime toDate(Object o, LocalDateTime defValue) {
if (o == null) {
return defValue;
}
if (o instanceof LocalDateTime) {
return (LocalDateTime) o;
}
try {
if (o.toString().contains(":"))
return Timestamp.valueOf(o.toString()).toLocalDateTime();
else
return java.sql.Date.valueOf(o.toString()).toLocalDate().atTime(0, 0);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy