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

org.hibernate.hql.internal.ast.SqlASTFactory Maven / Gradle / Ivy

There is a newer version: 6.5.0.CR2
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.hql.internal.ast;

import java.lang.reflect.Constructor;

import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.internal.ast.tree.AggregateNode;
import org.hibernate.hql.internal.ast.tree.BetweenOperatorNode;
import org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode;
import org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.BooleanLiteralNode;
import org.hibernate.hql.internal.ast.tree.CastFunctionNode;
import org.hibernate.hql.internal.ast.tree.NullNode;
import org.hibernate.hql.internal.ast.tree.SearchedCaseNode;
import org.hibernate.hql.internal.ast.tree.SimpleCaseNode;
import org.hibernate.hql.internal.ast.tree.CollectionFunction;
import org.hibernate.hql.internal.ast.tree.ConstructorNode;
import org.hibernate.hql.internal.ast.tree.CountNode;
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
import org.hibernate.hql.internal.ast.tree.DotNode;
import org.hibernate.hql.internal.ast.tree.FromClause;
import org.hibernate.hql.internal.ast.tree.FromElement;
import org.hibernate.hql.internal.ast.tree.IdentNode;
import org.hibernate.hql.internal.ast.tree.ImpliedFromElement;
import org.hibernate.hql.internal.ast.tree.InLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.IndexNode;
import org.hibernate.hql.internal.ast.tree.InitializeableNode;
import org.hibernate.hql.internal.ast.tree.InsertStatement;
import org.hibernate.hql.internal.ast.tree.IntoClause;
import org.hibernate.hql.internal.ast.tree.IsNotNullLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.IsNullLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.JavaConstantNode;
import org.hibernate.hql.internal.ast.tree.LiteralNode;
import org.hibernate.hql.internal.ast.tree.MapEntryNode;
import org.hibernate.hql.internal.ast.tree.MapKeyNode;
import org.hibernate.hql.internal.ast.tree.MapValueNode;
import org.hibernate.hql.internal.ast.tree.MethodNode;
import org.hibernate.hql.internal.ast.tree.OrderByClause;
import org.hibernate.hql.internal.ast.tree.ParameterNode;
import org.hibernate.hql.internal.ast.tree.QueryNode;
import org.hibernate.hql.internal.ast.tree.ResultVariableRefNode;
import org.hibernate.hql.internal.ast.tree.SelectClause;
import org.hibernate.hql.internal.ast.tree.SelectExpressionImpl;
import org.hibernate.hql.internal.ast.tree.SessionFactoryAwareNode;
import org.hibernate.hql.internal.ast.tree.SqlFragment;
import org.hibernate.hql.internal.ast.tree.SqlNode;
import org.hibernate.hql.internal.ast.tree.UnaryArithmeticNode;
import org.hibernate.hql.internal.ast.tree.UnaryLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.UpdateStatement;

import antlr.ASTFactory;
import antlr.Token;
import antlr.collections.AST;

/**
 * Custom AST factory the intermediate tree that causes ANTLR to create specialized
 * AST nodes, given the AST node type (from HqlSqlTokenTypes).   HqlSqlWalker registers
 * this factory with itself when it is initialized.
 *
 * @author Joshua
 */
public class SqlASTFactory extends ASTFactory implements HqlSqlTokenTypes {
	private HqlSqlWalker walker;

	/**
	 * Create factory with a specific mapping from token type
	 * to Java AST node type.  Your subclasses of ASTFactory
	 * can override and reuse the map stuff.
	 */
	public SqlASTFactory(HqlSqlWalker walker) {
		super();
		this.walker = walker;
	}

	/**
	 * Returns the class for a given token type (a.k.a. AST node type).
	 *
	 * @param tokenType The token type.
	 *
	 * @return Class - The AST node class to instantiate.
	 */
	public Class getASTNodeType(int tokenType) {
		switch ( tokenType ) {
			case SELECT:
			case QUERY:
				return QueryNode.class;
			case UPDATE:
				return UpdateStatement.class;
			case DELETE:
				return DeleteStatement.class;
			case INSERT:
				return InsertStatement.class;
			case INTO:
				return IntoClause.class;
			case FROM:
				return FromClause.class;
			case FROM_FRAGMENT:
				return FromElement.class;
			case IMPLIED_FROM:
				return ImpliedFromElement.class;
			case DOT:
				return DotNode.class;
			case INDEX_OP:
				return IndexNode.class;
			// Alias references and identifiers use the same node class.
			case ALIAS_REF:
			case IDENT:
				return IdentNode.class;
			case RESULT_VARIABLE_REF:
				return ResultVariableRefNode.class;
			case SQL_TOKEN:
				return SqlFragment.class;
			case METHOD_CALL:
				return MethodNode.class;
			case CAST:
				return CastFunctionNode.class;
			case ELEMENTS:
			case INDICES:
				return CollectionFunction.class;
			case SELECT_CLAUSE:
				return SelectClause.class;
			case SELECT_EXPR:
				return SelectExpressionImpl.class;
			case AGGREGATE:
				return AggregateNode.class;
			case COUNT:
				return CountNode.class;
			case CONSTRUCTOR:
				return ConstructorNode.class;
			case NUM_INT:
			case NUM_FLOAT:
			case NUM_LONG:
			case NUM_DOUBLE:
			case NUM_BIG_INTEGER:
			case NUM_BIG_DECIMAL:
			case QUOTED_STRING:
				return LiteralNode.class;
			case TRUE:
			case FALSE:
				return BooleanLiteralNode.class;
			case JAVA_CONSTANT:
				return JavaConstantNode.class;
			case ORDER:
				return OrderByClause.class;
			case PLUS:
			case MINUS:
			case STAR:
			case DIV:
			case MOD:
				return BinaryArithmeticOperatorNode.class;
			case UNARY_MINUS:
			case UNARY_PLUS:
				return UnaryArithmeticNode.class;
			case CASE2:
				return SimpleCaseNode.class;
			case CASE:
				return SearchedCaseNode.class;
			case PARAM:
			case NAMED_PARAM:
				return ParameterNode.class;
			case EQ:
			case NE:
			case LT:
			case GT:
			case LE:
			case GE:
			case LIKE:
			case NOT_LIKE:
				return BinaryLogicOperatorNode.class;
			case IN:
			case NOT_IN:
				return InLogicOperatorNode.class;
			case BETWEEN:
			case NOT_BETWEEN:
				return BetweenOperatorNode.class;
			case IS_NULL:
				return IsNullLogicOperatorNode.class;
			case IS_NOT_NULL:
				return IsNotNullLogicOperatorNode.class;
			case EXISTS:
				return UnaryLogicOperatorNode.class;
			case KEY: {
				return MapKeyNode.class;
			}
			case VALUE: {
				return MapValueNode.class;
			}
			case ENTRY: {
				return MapEntryNode.class;
			}
			case NULL : {
				return NullNode.class;
			}
			default:
				return SqlNode.class;
		}
	}

	@SuppressWarnings("unchecked")
	protected AST createUsingCtor(Token token, String className) {
		Class c;
		AST t;
		try {
			c = Class.forName( className );
			Class[] tokenArgType = new Class[] {antlr.Token.class};
			Constructor ctor = c.getConstructor( tokenArgType );
			if ( ctor != null ) {
				t = (AST) ctor.newInstance( token );
				initializeSqlNode( t );
			}
			else {
				// just do the regular thing if you can't find the ctor
				// Your AST must have default ctor to use this.
				t = create( c );
			}
		}
		catch (Exception e) {
			throw new IllegalArgumentException( "Invalid class or can't make instance, " + className );
		}
		return t;
	}

	private void initializeSqlNode(AST t) {
		// Initialize SQL nodes here.
		if ( t instanceof InitializeableNode ) {
			InitializeableNode initializeableNode = (InitializeableNode) t;
			initializeableNode.initialize( walker );
		}
		if ( t instanceof SessionFactoryAwareNode ) {
			( (SessionFactoryAwareNode) t ).setSessionFactory( walker.getSessionFactoryHelper().getFactory() );
		}
	}

	/**
	 * Actually instantiate the AST node.
	 *
	 * @param c The class to instantiate.
	 *
	 * @return The instantiated and initialized node.
	 */
	protected AST create(Class c) {
		AST t;
		try {
			t = (AST) c.newInstance();
			initializeSqlNode( t );
		}
		catch (Exception e) {
			error( "Can't create AST Node " + c.getName() );
			return null;
		}
		return t;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy