alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (MethodNode.java)

This example Hibernate source code file (MethodNode.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

ast, ast, dotnode, fromelement, fromelement, fromreferencenode, override, semanticexception, semanticexception, sqlfunction, sqlnode, string, string, type, util

The Hibernate MethodNode.java source code

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Middleware LLC.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 *
 */
package org.hibernate.hql.internal.ast.tree;
import java.util.Arrays;

import org.hibernate.hql.internal.CollectionProperties;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
import org.hibernate.hql.internal.ast.TypeDiscriminatorMetadata;
import org.hibernate.hql.internal.ast.util.ASTUtil;
import org.hibernate.hql.internal.ast.util.ColumnHelper;
import org.hibernate.persister.collection.CollectionPropertyNames;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
import antlr.SemanticException;
import antlr.collections.AST;

/**
 * Represents a method call.
 *
 * @author josh
 */
public class MethodNode extends AbstractSelectExpression implements FunctionNode {

    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, MethodNode.class.getName());

	private String methodName;
	private FromElement fromElement;
	private String[] selectColumns;
	private SQLFunction function;
	private boolean inSelect;

	public void resolve(boolean inSelect) throws SemanticException {
		// Get the function name node.
		AST name = getFirstChild();
		initializeMethodNode( name, inSelect );
		AST exprList = name.getNextSibling();
		// If the expression list has exactly one expression, and the type of the expression is a collection
		// then this might be a collection function, such as index(c) or size(c).
		if ( ASTUtil.hasExactlyOneChild( exprList ) ) {
			if ( "type".equals( methodName ) ) {
				typeDiscriminator( exprList.getFirstChild() );
				return;
			}
			if ( isCollectionPropertyMethod() ) {
				collectionProperty( exprList.getFirstChild(), name );
				return;
			}
		}

		dialectFunction( exprList );
	}

	private void typeDiscriminator(AST path) throws SemanticException {
		if ( path == null ) {
			throw new SemanticException( "type() discriminator reference has no path!" );
		}

		FromReferenceNode pathAsFromReferenceNode = (FromReferenceNode) path;
		FromElement fromElement = pathAsFromReferenceNode.getFromElement();
		TypeDiscriminatorMetadata typeDiscriminatorMetadata = fromElement.getTypeDiscriminatorMetadata();

		setDataType( typeDiscriminatorMetadata.getResolutionType() );
		setText( typeDiscriminatorMetadata.getSqlFragment() );
		setType( SqlTokenTypes.SQL_TOKEN );
	}

	public SQLFunction getSQLFunction() {
		return function;
	}

	public Type getFirstArgumentType() {
		AST argument = getFirstChild();
		while ( argument != null ) {
			if ( argument instanceof SqlNode ) {
				final Type type = ( (SqlNode) argument ).getDataType();
				if ( type != null ) {
					return type;
				}
				argument = argument.getNextSibling();
			}
		}
		return null;
	}

	private void dialectFunction(AST exprList) {
		function = getSessionFactoryHelper().findSQLFunction( methodName );
		if ( function != null ) {
			AST firstChild = exprList != null ? exprList.getFirstChild() : null;
			Type functionReturnType = getSessionFactoryHelper()
					.findFunctionReturnType( methodName, firstChild );
			setDataType( functionReturnType );
		}
		//TODO:
		/*else {
			methodName = (String) getWalker().getTokenReplacements().get( methodName );
		}*/
	}

	public boolean isCollectionPropertyMethod() {
		return CollectionProperties.isAnyCollectionProperty( methodName );
	}

	public void initializeMethodNode(AST name, boolean inSelect) {
		name.setType( SqlTokenTypes.METHOD_NAME );
		String text = name.getText();
		methodName = text.toLowerCase();	// Use the lower case function name.
		this.inSelect = inSelect;			// Remember whether we're in a SELECT clause or not.
	}

	private String getMethodName() {
		return methodName;
	}

	private void collectionProperty(AST path, AST name) throws SemanticException {
		if ( path == null ) {
			throw new SemanticException( "Collection function " + name.getText() + " has no path!" );
		}

		SqlNode expr = ( SqlNode ) path;
		Type type = expr.getDataType();
        LOG.debugf("collectionProperty() :  name=%s type=%s", name, type);

		resolveCollectionProperty( expr );
	}

	@Override
    public boolean isScalar() throws SemanticException {
		// Method expressions in a SELECT should always be considered scalar.
		return true;
	}

	public void resolveCollectionProperty(AST expr) throws SemanticException {
		String propertyName = CollectionProperties.getNormalizedPropertyName( getMethodName() );
		if ( expr instanceof FromReferenceNode ) {
			FromReferenceNode collectionNode = ( FromReferenceNode ) expr;
			// If this is 'elements' then create a new FROM element.
			if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( propertyName ) ) {
				handleElements( collectionNode, propertyName );
			}
			else {
				// Not elements(x)
				fromElement = collectionNode.getFromElement();
				setDataType( fromElement.getPropertyType( propertyName, propertyName ) );
				selectColumns = fromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect );
			}
			if ( collectionNode instanceof DotNode ) {
				prepareAnyImplicitJoins( ( DotNode ) collectionNode );
			}
			if ( !inSelect ) {
				fromElement.setText( "" );
				fromElement.setUseWhereFragment( false );
			}
			prepareSelectColumns( selectColumns );
			setText( selectColumns[0] );
			setType( SqlTokenTypes.SQL_TOKEN );
		}
		else {
			throw new SemanticException(
					"Unexpected expression " + expr +
					" found for collection function " + propertyName
				);
		}
	}

	private void prepareAnyImplicitJoins(DotNode dotNode) throws SemanticException {
		if ( dotNode.getLhs() instanceof DotNode ) {
			DotNode lhs = ( DotNode ) dotNode.getLhs();
			FromElement lhsOrigin = lhs.getFromElement();
			if ( lhsOrigin != null && "".equals( lhsOrigin.getText() ) ) {
				String lhsOriginText = lhsOrigin.getQueryable().getTableName() +
				        " " + lhsOrigin.getTableAlias();
				lhsOrigin.setText( lhsOriginText );
			}
			prepareAnyImplicitJoins( lhs );
		}
	}

	private void handleElements(FromReferenceNode collectionNode, String propertyName) {
		FromElement collectionFromElement = collectionNode.getFromElement();
		QueryableCollection queryableCollection = collectionFromElement.getQueryableCollection();

		String path = collectionNode.getPath() + "[]." + propertyName;
        LOG.debugf("Creating elements for %s", path);

		fromElement = collectionFromElement;
		if ( !collectionFromElement.isCollectionOfValuesOrComponents() ) {
			getWalker().addQuerySpaces( queryableCollection.getElementPersister().getQuerySpaces() );
		}

		setDataType( queryableCollection.getElementType() );
		selectColumns = collectionFromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect );
	}

	public void setScalarColumnText(int i) throws SemanticException {
		if ( selectColumns == null ) { 	// Dialect function
			ColumnHelper.generateSingleScalarColumn( this, i );
		}
		else {	// Collection 'property function'
			ColumnHelper.generateScalarColumns( this, selectColumns, i );
		}
	}

	protected void prepareSelectColumns(String[] columns) {
	}

	@Override
    public FromElement getFromElement() {
		return fromElement;
	}

	public String getDisplayText() {
		return "{" +
				"method=" + getMethodName() +
				",selectColumns=" + ( selectColumns == null ?
						null : Arrays.asList( selectColumns ) ) +
				",fromElement=" + fromElement.getTableAlias() +
				"}";
	}
}

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate MethodNode.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.