All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.venky.swf.sql.parser.SQLExpressionParser Maven / Gradle / Ivy

The newest version!
package com.venky.swf.sql.parser;

import java.io.InputStream;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.venky.core.string.StringUtil;
import com.venky.parse.Rule;
import com.venky.parse.Rule.Element;
import com.venky.parse.character.CharRange;
import com.venky.parse.character.Exclude;
import com.venky.parse.character.Include;
import com.venky.parse.composite.Any;
import com.venky.parse.composite.CharSequence;
import com.venky.parse.composite.Multiple;
import com.venky.parse.composite.OneOrMore;
import com.venky.parse.composite.Sequence;
import com.venky.parse.composite.ZeroOrMore;
import com.venky.swf.db.Database;
import com.venky.swf.db.JdbcTypeHelper.TypeRef;
import com.venky.swf.db.model.Model;
import com.venky.swf.db.table.BindVariable;
import com.venky.swf.db.table.Table;
import com.venky.swf.db.table.Table.ColumnDescriptor;
import com.venky.swf.sql.Conjunction;
import com.venky.swf.sql.Expression;
import com.venky.swf.sql.Operator;


public class SQLExpressionParser {
	
	Table table = null; 
	public SQLExpressionParser(Class modelClass){
		table = Database.getTable(modelClass);
	}
	
	public Expression parse(InputStream is){
		return parse(StringUtil.read(is));
	}
	public Expression parse(String expression){
		ExpressionRule rule = new ExpressionRule();
		Expression ret = null; 
		if (rule.match(expression) && expression.length() == rule.getMatch().length()){
			Element e = rule.getMatch();
			ret = new Expression(table.getReflector().getPool(),Conjunction.AND);
			parse(e,ret);
		}
		return ret;
	}

	private void parse(Element e, Expression parentExpression){
		if (e.getRule().getClass() == EQ.class){
			parentExpression.add(createExpression(e, Operator.EQ));
		}else if (e.getRule().getClass() == LT.class){
			parentExpression.add(createExpression(e, Operator.LT));
		}else if (e.getRule().getClass() == GT.class){
			parentExpression.add(createExpression(e, Operator.GT));
		}else if (e.getRule().getClass() == LE.class){
			parentExpression.add(createExpression(e, Operator.LE));
		}else if (e.getRule().getClass() == GE.class){
			parentExpression.add(createExpression(e, Operator.GE));
		}else if (e.getRule().getClass() == NE.class){
			parentExpression.add(createExpression(e, Operator.NE));
		}else if (e.getRule().getClass() == LIKE.class){
			parentExpression.add(createExpression(e, Operator.LK));
		}else if (e.getRule().getClass() == IN.class){
			parentExpression.add(createExpression(e, Operator.IN));
		}else if (e.getRule().getClass() == ISNULL.class){
			parentExpression.add(createExpression(e, Operator.EQ));
		}else if (e.getRule().getClass() == IS_NOTNULL.class){
			parentExpression.add(createExpression(e, Operator.NE));
		}else {
			Expression ex = null;
			if (e.getRule().getClass() == And.class){
				ex = new Expression(table.getReflector().getPool(),Conjunction.AND);
			}else if (e.getRule().getClass() == Or.class){
				ex = new Expression(table.getReflector().getPool(),Conjunction.OR);
			}
			if (ex != null){
				parentExpression.add(ex);
				parentExpression = ex;
			}
		}
			
		for (Element child: e.getChildren()){
			parse(child,parentExpression);
		}
	}
	private Expression createExpression(Element e, Operator op){
		String columnName = columnName(e);
		ColumnDescriptor cd = table.getReflector().getColumnDescriptor(columnName);
		if (cd == null){
			throw new RuntimeException(table.getRealTableName() + " does not have column " + columnName);
		}
		if (e.getRule().getClass() == ISNULL.class || e.getRule().getClass() == IS_NOTNULL.class){
			return new Expression(table.getReflector().getPool(),columnName,op);
		}else { 
			List columnValues = columnValues(e,cd);
			return new Expression(table.getReflector().getPool(),columnName,op,columnValues.toArray());
		}
	}
	private String columnName(Element e){
		List columnName = hunt(ColumnName.class,e);
		assert (columnName.size() == 1);
		return columnName.get(0).getText().trim();
	}
	private List columnValues(Element e, ColumnDescriptor cd){
		Collection columnValues = hunt(ColumnValue.class,e);
		List values = new ArrayList();
		for (Element columnValue:columnValues){
			String sValue = columnValue.getText().trim();
			if (sValue.startsWith("'")){
				List quotedValues =  hunt(QuotedValue.class,columnValue);
				assert quotedValues.size() == 1 ;
				sValue = quotedValues.get(0).getText();
			}
			Object value = sValue;
			if (cd != null){
				int jdbcType = cd.getJDBCType();
				if (jdbcType != Types.VARCHAR){
					List> refs = Database.getJdbcTypeHelper(table.getReflector().getPool()).getTypeRefs(jdbcType);
					TypeRef ref = null;
					if (refs.size() == 1){
						ref = refs.get(0);
					}else {
						String field = this.table.getReflector().getFieldName(cd.getName());
						ref = Database.getJdbcTypeHelper(table.getReflector().getPool()).getTypeRef(this.table.getReflector().getFieldGetter(field).getReturnType());
					}
					value = ref.getTypeConverter().valueOf(sValue);
				}
			}
			values.add(new BindVariable(table.getReflector().getPool(),value));
		}
		return values;
	}
	
	private List hunt(Class elementForRule , Element within){
		List ret = new ArrayList();
		if (within.getRule().getClass() == elementForRule){
			ret.add(within);
		}else {
			for (Element child : within.getChildren()){
				Collection hunted = hunt(elementForRule,child);
				if (hunted != null){
					ret.addAll(hunted);
				}
			}
		}
		return ret;
	}
	
	
	public static class ExpressionRule extends PossiblyEnclosed {
		public ExpressionRule(){
			super(new Compound(new Operation()));
		}
	}
	
	public static class Operation extends PossiblyEnclosed {
		public Operation(){
			super(new Compound(new PossiblyEnclosed(new Compound(new SimpleOperation()))));
		}
	}

	
	public static class PossiblyEnclosed extends Rule {
		private Rule ruleTemplate = null;
		private int maxNumBrackets = UNKNOWN; 
		private static final int UNKNOWN = -1;
		public PossiblyEnclosed(Rule rule){
			this(rule,UNKNOWN);
		}
		public PossiblyEnclosed(Rule rule,int maxnumBrackets){
			this.ruleTemplate = rule;
			this.maxNumBrackets = maxnumBrackets;
		}
		
		@Override
		public boolean match(String input, int offset) {
			if (maxNumBrackets == UNKNOWN){
				Rule bracket = zeroOrMore(openParen());
				boolean bracketsPresent = bracket.match(input, offset);
				if (bracketsPresent){
					this.maxNumBrackets = bracket.getMatch().length();
				}
			}
			for (int i = 0 ; i <= maxNumBrackets ; i ++){
				Rule r = createRule(i);
				if (r.match(input,offset)){
					Element match = new Element(this);
					match.add(r.getMatch());
					setMatch(match);
					return true;
				}
			}
			return false;
		}
		
		private Rule createRule(int numBrackets){
			return new Sequence(new Multiple(openParen(),numBrackets,numBrackets), 
					ruleTemplate.createClone() , new Multiple(closeParen(),numBrackets,numBrackets));
		}
	}
	
	public static class Compound extends Any{
		public Compound(Rule rule){
			super (new And(rule.createClone()),new Or(rule.createClone()),rule.createClone());
		}
	}
	
	public static class And extends Sequence {
		public And(Rule rule){
			super(rule.createClone(), oneOrMore(sequence(new CharSequence("AND"), spaces(), rule.createClone())));
		}
	}
	public static class Or extends Sequence {
		public Or(Rule rule){
			super(rule.createClone(), oneOrMore(sequence(new CharSequence("OR"), spaces(), rule.createClone())));
		}
	}



	public static class ColumnName extends Sequence{
		public ColumnName(){
			super(letter(),new ZeroOrMore(new Any(letter(),underscore(),digit())),spaces());
		}
	}

	public static class ColumnValue extends Any {
		public ColumnValue(){
			super(new Sequence(new Include('\''),new QuotedValue(), new Include('\''),spaces()),
					new Sequence(new OneOrMore(new Exclude(' ','\t','\r','\n','\f','(', ')', '\'' , '>' , '<' , '=' , '!')),spaces()));
		}
	}
	
	public static class QuotedValue extends OneOrMore {
		public QuotedValue(){
			super(new Exclude('\''));
		}
	}

	public static class SimpleOperation extends Any{
		public SimpleOperation(){
			super(new EQ(),new LT(), new GT(), new LE() ,new GE(), new NE() , new LIKE() , new IN() , new ISNULL() , new IS_NOTNULL());
		}
	}
	public static class ISNULL extends Sequence { 
		public ISNULL(){
			super(columnName(), new CharSequence("IS"),spaces(), new CharSequence("NULL"), spaces() );
		}
	}
	public static class IS_NOTNULL extends Sequence { 
		public IS_NOTNULL(){
			super(columnName(), new CharSequence("IS"),spaces(), new CharSequence("NOT"),spaces(), new CharSequence("NULL"), spaces());
		}
	}
	public static class EQ extends Sequence{
		public EQ(){
			super(columnName(), new Include('='),spaces() , columnValue());
		}
	}
	public static class LT extends Sequence{
		public LT(){
			super(columnName(), new Include('<'),spaces() , columnValue());
		}
	}
	public static class GT extends Sequence{
		public GT(){
			super(columnName(), new Include('>'),spaces() , columnValue());
		}
	}

	public static class LE extends Sequence{
		public LE(){
			super(columnName(), new Include('<'), new Include('='), spaces() , columnValue());
		}
	}

	public static class GE extends Sequence{
		public GE(){
			super(columnName(), new Include('>'), new Include('='), spaces() , columnValue());
		}
	}
	public static class NE extends Any{
		public NE(){
			super(
					new Sequence(columnName(), new Include('!'), new Include('='), spaces() , columnValue()),
					new Sequence(columnName(), new Include('<'), new Include('>'), spaces() , columnValue())
			);
		}
	}
	
	public static class LIKE extends Sequence{
		public LIKE(){
			super(columnName(), new CharSequence("LIKE"), spaces() , columnValue());
		}
	}
	
	
	public static class IN extends Sequence {
		public IN(){
			super(columnName(), new CharSequence("IN"),spaces() , columnValues());
		}
	}


	public static Rule columnName(){
		return new ColumnName();
	}
	
	public static Rule columnValue(){
		return new ColumnValue();
	}
	
	public static Rule columnValues(){
		return new Sequence( openParen(), 
				columnValue() , new ZeroOrMore(new Sequence(new Include(',') , columnValue())) , 
				closeParen() );
	}
	
	public static Rule underscore(){
		return new Include('_');
	}


	public static Rule openParen(){
		return new Sequence(new Include('('),spaces());
	}
	public static Rule closeParen(){
		return new Sequence(new Include(')'),spaces());
	}

	public static Rule letter(){
		return new Any(new CharRange('A', 'Z'),new CharRange('a', 'z'));
	}
	public static Rule digit(){
		return new CharRange('0','9');
	}
	public static Rule whiteSpace(){
		return new Include(' ','\t','\r','\n','\f');
	}
	
	public static Rule spaces() {
		return new ZeroOrMore(whiteSpace());
	}
	
	public static Rule sequence(Rule... rules){
		return new Sequence(rules);
	}

	public static Rule any(Rule... rules){
		return new Any(rules);
	}
	
	public static Rule oneOrMore(Rule rule){
		return new OneOrMore(rule);
	}
	public static Rule zeroOrMore(Rule rule){
		return new ZeroOrMore(rule);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy