FileDocCategorySizeDatePackage
LiteralProcessor.javaAPI DocHibernate 3.2.510274Wed Mar 07 15:41:22 GMT 2007org.hibernate.hql.ast.util

LiteralProcessor

public class LiteralProcessor extends Object implements org.hibernate.hql.antlr.HqlSqlTokenTypes
A delegate that handles literals and constants for HqlSqlWalker, performing the token replacement functions and classifying literals.
author
josh Sep 2, 2004 7:15:30 AM

Fields Summary
public static final int
EXACT
Indicates that Float and Double literal values should be treated using the SQL "exact" format (i.e., '.001')
public static final int
APPROXIMATE
Indicates that Float and Double literal values should be treated using the SQL "approximate" format (i.e., '1E-3')
public static int
DECIMAL_LITERAL_FORMAT
In what format should Float and Double literal values be sent to the database?
private static final Log
log
private org.hibernate.hql.ast.HqlSqlWalker
walker
private static final DecimalFormatter[]
formatters
Constructors Summary
public LiteralProcessor(org.hibernate.hql.ast.HqlSqlWalker hqlSqlWalker)


	   
		this.walker = hqlSqlWalker;
	
Methods Summary
public java.lang.StringdetermineDecimalRepresentation(java.lang.String text, int type)

		String literalValue = text;
		if ( type == NUM_FLOAT ) {
			if ( literalValue.endsWith( "f" ) || literalValue.endsWith( "F" ) ) {
				literalValue = literalValue.substring( 0, literalValue.length() - 1 );
			}
		}
		else if ( type == NUM_DOUBLE ) {
			if ( literalValue.endsWith( "d" ) || literalValue.endsWith( "D" ) ) {
				literalValue = literalValue.substring( 0, literalValue.length() - 1 );
			}
		}

		BigDecimal number = null;
		try {
			number = new BigDecimal( literalValue );
		}
		catch( Throwable t ) {
			throw new HibernateException( "Could not parse literal [" + text + "] as big-decimal", t );
		}

		return formatters[ DECIMAL_LITERAL_FORMAT ].format( number );
	
private java.lang.StringdetermineIntegerRepresentation(java.lang.String text, int type)

		try {
			if ( type == NUM_INT ) {
				try {
					return Integer.valueOf( text ).toString();
				}
				catch( NumberFormatException e ) {
					log.trace( "could not format incoming text [" + text + "] as a NUM_INT; assuming numeric overflow and attempting as NUM_LONG" );
				}
			}
			String literalValue = text;
			if ( literalValue.endsWith( "l" ) || literalValue.endsWith( "L" ) ) {
				literalValue = literalValue.substring( 0, literalValue.length() - 1 );
			}
			return Long.valueOf( literalValue ).toString();
		}
		catch( Throwable t ) {
			throw new HibernateException( "Could not parse literal [" + text + "] as integer", t );
		}
	
public booleanisAlias(java.lang.String alias)

		FromClause from = walker.getCurrentFromClause();
		while ( from.isSubQuery() ) {
			if ( from.containsClassAlias(alias) ) {
				return true;
			}
			from = from.getParentFromClause();
		}
		return from.containsClassAlias(alias);
	
public voidlookupConstant(org.hibernate.hql.ast.tree.DotNode node)

		String text = ASTUtil.getPathText( node );
		Queryable persister = walker.getSessionFactoryHelper().findQueryableUsingImports( text );
		if ( persister != null ) {
			// the name of an entity class
			final String discrim = persister.getDiscriminatorSQLValue();
			node.setDataType( persister.getDiscriminatorType() );
			if ( InFragment.NULL.equals(discrim) || InFragment.NOT_NULL.equals(discrim) ) {
				throw new InvalidPathException( "subclass test not allowed for null or not null discriminator: '" + text + "'" );
			}
			else {
				setSQLValue( node, text, discrim ); //the class discriminator value
			}
		}
		else {
			Object value = ReflectHelper.getConstantValue( text );
			if ( value == null ) {
				throw new InvalidPathException( "Invalid path: '" + text + "'" );
			}
			else {
				setConstantValue( node, text, value );
			}
		}
	
public voidprocessBoolean(antlr.collections.AST constant)

		// TODO: something much better - look at the type of the other expression!
		// TODO: Have comparisonExpression and/or arithmeticExpression rules complete the resolution of boolean nodes.
		String replacement = ( String ) walker.getTokenReplacements().get( constant.getText() );
		if ( replacement != null ) {
			constant.setText( replacement );
		}
		else {
			boolean bool = "true".equals( constant.getText().toLowerCase() );
			Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect();
			constant.setText( dialect.toBooleanValueString(bool) );
		}
	
public voidprocessConstant(antlr.collections.AST constant, boolean resolveIdent)

		// If the constant is an IDENT, figure out what it means...
		boolean isIdent = ( constant.getType() == IDENT || constant.getType() == WEIRD_IDENT );
		if ( resolveIdent && isIdent && isAlias( constant.getText() ) ) { // IDENT is a class alias in the FROM.
			IdentNode ident = ( IdentNode ) constant;
			// Resolve to an identity column.
			ident.resolve(false, true);
		}
		else {	// IDENT might be the name of a class.
			Queryable queryable = walker.getSessionFactoryHelper().findQueryableUsingImports( constant.getText() );
			if ( isIdent && queryable != null ) {
				constant.setText( queryable.getDiscriminatorSQLValue() );
			}
			// Otherwise, it's a literal.
			else {
				processLiteral( constant );
			}
		}
	
private voidprocessLiteral(antlr.collections.AST constant)

		String replacement = ( String ) walker.getTokenReplacements().get( constant.getText() );
		if ( replacement != null ) {
			if ( log.isDebugEnabled() ) {
				log.debug( "processConstant() : Replacing '" + constant.getText() + "' with '" + replacement + "'" );
			}
			constant.setText( replacement );
		}
	
public voidprocessNumeric(antlr.collections.AST literal)

		if ( literal.getType() == NUM_INT || literal.getType() == NUM_LONG ) {
			literal.setText( determineIntegerRepresentation( literal.getText(), literal.getType() ) );
		}
		else if ( literal.getType() == NUM_FLOAT || literal.getType() == NUM_DOUBLE ) {
			literal.setText( determineDecimalRepresentation( literal.getText(), literal.getType() ) );
		}
		else {
			log.warn( "Unexpected literal token type [" + literal.getType() + "] passed for numeric processing" );
		}
	
private voidsetConstantValue(org.hibernate.hql.ast.tree.DotNode node, java.lang.String text, java.lang.Object value)

		if ( log.isDebugEnabled() ) {
			log.debug( "setConstantValue() " + text + " -> " + value + " " + value.getClass().getName() );
		}
		node.setFirstChild( null );	// Chop off the rest of the tree.
		if ( value instanceof String ) {
			node.setType( SqlTokenTypes.QUOTED_STRING );
		}
		else if ( value instanceof Character ) {
			node.setType( SqlTokenTypes.QUOTED_STRING );
		}
		else if ( value instanceof Byte ) {
			node.setType( SqlTokenTypes.NUM_INT );
		}
		else if ( value instanceof Short ) {
			node.setType( SqlTokenTypes.NUM_INT );
		}
		else if ( value instanceof Integer ) {
			node.setType( SqlTokenTypes.NUM_INT );
		}
		else if ( value instanceof Long ) {
			node.setType( SqlTokenTypes.NUM_LONG );
		}
		else if ( value instanceof Double ) {
			node.setType( SqlTokenTypes.NUM_DOUBLE );
		}
		else if ( value instanceof Float ) {
			node.setType( SqlTokenTypes.NUM_FLOAT );
		}
		else {
			node.setType( SqlTokenTypes.CONSTANT );
		}
		Type type;
		try {
			type = TypeFactory.heuristicType( value.getClass().getName() );
		}
		catch ( MappingException me ) {
			throw new QueryException( me );
		}
		if ( type == null ) {
			throw new QueryException( QueryTranslator.ERROR_CANNOT_DETERMINE_TYPE + node.getText() );
		}
		try {
			LiteralType literalType = ( LiteralType ) type;
			Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect();
			node.setText( literalType.objectToSQLString( value, dialect ) );
		}
		catch ( Exception e ) {
			throw new QueryException( QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + node.getText(), e );
		}
		node.setDataType( type );
		node.setResolvedConstant( text );
	
private voidsetSQLValue(org.hibernate.hql.ast.tree.DotNode node, java.lang.String text, java.lang.String value)

		if ( log.isDebugEnabled() ) {
			log.debug( "setSQLValue() " + text + " -> " + value );
		}
		node.setFirstChild( null );	// Chop off the rest of the tree.
		node.setType( SqlTokenTypes.SQL_TOKEN );
		node.setText(value);
		node.setResolvedConstant( text );