⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dotnode.java

📁 好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.2.0
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// $Id: DotNode.java 9046 2006-01-13 03:10:57Z steveebersole $
package org.hibernate.hql.ast.tree;

import org.hibernate.QueryException;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.CollectionProperties;
import org.hibernate.hql.antlr.SqlTokenTypes;
import org.hibernate.hql.ast.util.ASTPrinter;
import org.hibernate.hql.ast.util.ASTUtil;
import org.hibernate.hql.ast.util.ColumnHelper;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;

import antlr.SemanticException;
import antlr.collections.AST;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Represents a reference to a property or alias expression.  This should duplicate the relevant behaviors in
 * PathExpressionParser.
 * <hr>
 * User: josh<br>
 * Date: Dec 16, 2003<br>
 * Time: 8:03:09 AM
 */
public class DotNode extends FromReferenceNode implements DisplayableNode, SelectExpression {

	/**
	 * A logger for this class.
	 */
	private static final Log log = LogFactory.getLog( DotNode.class );

	private static final int DEREF_UNKNOWN = 0;
	private static final int DEREF_ENTITY = 1;
	private static final int DEREF_COMPONENT = 2;
	private static final int DEREF_COLLECTION = 3;
	private static final int DEREF_PRIMITIVE = 4;
	private static final int DEREF_IDENTIFIER = 5;
	private static final int DEREF_JAVA_CONSTANT = 6;

	/**
	 * The identifier that is the name of the property.
	 */
	private String propertyName;
	/**
	 * The full path, to the root alias of this dot node.
	 */
	private String path;
	/**
	 * The unresolved property path relative to this dot node.
	 */
	private String propertyPath;

	/**
	 * The column names that this resolves to.
	 */
	private String[] columns;

	/**
	 * The type of join to create.   Default is an inner join.
	 */
	private int joinType = JoinFragment.INNER_JOIN;

	/**
	 * Fetch join or not.
	 */
	private boolean fetch = false;

	/**
	 * The type of dereference that hapened (DEREF_xxx).
	 */
	private int dereferenceType = DEREF_UNKNOWN;

	private FromElement impliedJoin;

	/**
	 * Sets the join type for the '.' node (JoinFragment.XXX).
	 *
	 * @param joinType
	 * @see JoinFragment
	 */
	public void setJoinType(int joinType) {
		this.joinType = joinType;
	}

	private String[] getColumns() throws QueryException {
		if ( columns == null ) {
			// Use the table fromElement and the property name to get the array of column names.
			String tableAlias = getLhs().getFromElement().getTableAlias();
			columns = getFromElement().toColumns( tableAlias, propertyPath, false );
		}
		return columns;
	}

	public String getDisplayText() {
		StringBuffer buf = new StringBuffer();
		FromElement fromElement = getFromElement();
		buf.append( "{propertyName=" ).append( propertyName );
		buf.append( ",dereferenceType=" ).append( ASTPrinter.getConstantName( getClass(), dereferenceType ) );
		buf.append( ",propertyPath=" ).append( propertyPath );
		buf.append( ",path=" ).append( getPath() );
		if ( fromElement != null ) {
			buf.append( ",tableAlias=" ).append( fromElement.getTableAlias() );
			buf.append( ",className=" ).append( fromElement.getClassName() );
			buf.append( ",classAlias=" ).append( fromElement.getClassAlias() );
		}
		else {
			buf.append( ",no from element" );
		}
		buf.append( '}' );
		return buf.toString();
	}

	/**
	 * Resolves the left hand side of the DOT.
	 *
	 * @throws SemanticException
	 */
	public void resolveFirstChild() throws SemanticException {
		FromReferenceNode lhs = ( FromReferenceNode ) getFirstChild();
		SqlNode property = ( SqlNode ) lhs.getNextSibling();

		// Set the attributes of the property reference expression.
		String propName = property.getText();
		propertyName = propName;
		// If the uresolved property path isn't set yet, just use the property name.
		if ( propertyPath == null ) {
			propertyPath = propName;
		}
		// Resolve the LHS fully, generate implicit joins.  Pass in the property name so that the resolver can
		// discover foreign key (id) properties.
		lhs.resolve( true, true, null, this );
		setFromElement( lhs.getFromElement() );			// The 'from element' that the property is in.
	}
	
	public void resolveInFunctionCall(boolean generateJoin, boolean implicitJoin) throws SemanticException {
		if ( isResolved() ) {
			return;
		}
		Type propertyType = prepareLhs();			// Prepare the left hand side and get the data type.
		if ( propertyType!=null && propertyType.isCollectionType() ) {
			resolveIndex(null);
		}
		else {
			resolveFirstChild();
			super.resolve(generateJoin, implicitJoin);
		}
	}


	public void resolveIndex(AST parent) throws SemanticException {
		if ( isResolved() ) {
			return;
		}
		Type propertyType = prepareLhs();			// Prepare the left hand side and get the data type.
		dereferenceCollection( ( CollectionType ) propertyType, true, true, null, parent );
	}

	public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) 
	throws SemanticException {
		// If this dot has already been resolved, stop now.
		if ( isResolved() ) {
			return;
		}
		Type propertyType = prepareLhs(); // Prepare the left hand side and get the data type.

		// If there is no data type for this node, and we're at the end of the path (top most dot node), then
		// this might be a Java constant.
		if ( propertyType == null ) {
			if ( parent == null ) {
				getWalker().getLiteralProcessor().lookupConstant( this );
			}
			// If the propertyType is null and there isn't a parent, just 
			// stop now... there was a problem resolving the node anyway.
			return;
		}

		// The property is a component...
		if ( propertyType.isComponentType() ) {
			checkLhsIsNotCollection();
			dereferenceComponent( parent );
			initText();
		}
		// The property is another class..
		else if ( propertyType.isEntityType() ) {
			checkLhsIsNotCollection();
			dereferenceEntity( ( EntityType ) propertyType, implicitJoin, classAlias, generateJoin, parent );
			initText();
		}
		// The property is a collection...
		else if ( propertyType.isCollectionType() ) {
			checkLhsIsNotCollection();
			dereferenceCollection( ( CollectionType ) propertyType, implicitJoin, false, classAlias, parent );
		}
		else {	// Otherwise, this is a primitive type.
			dereferenceType = DEREF_PRIMITIVE;
			initText();
		}
		setResolved();
	}
	
	private void initText() {
		String[] cols = getColumns();
		String text = StringHelper.join( ", ", cols );
		if ( cols.length > 1 && getWalker().isComparativeExpressionClause() ) {
			text = "(" + text + ")";
		}
		setText( text );
	}

	private Type prepareLhs() throws SemanticException {
		FromReferenceNode lhs = getLhs();
		lhs.prepareForDot( propertyName );
		Type propertyType = getDataType();
		return propertyType;
	}

	private void dereferenceCollection(CollectionType collectionType, boolean implicitJoin, boolean indexed, String classAlias, AST parent) 
	throws SemanticException {
		
		dereferenceType = DEREF_COLLECTION;
		String role = collectionType.getRole();
		
		//foo.bars.size (also handles deprecated stuff like foo.bars.maxelement for backwardness)
		boolean isSizeProperty = getNextSibling()!=null && 
			CollectionProperties.isAnyCollectionProperty( getNextSibling().getText() );

		if ( isSizeProperty ) indexed = true; //yuck!

		QueryableCollection queryableCollection = getSessionFactoryHelper().requireQueryableCollection( role );
		String propName = getPath();
		FromClause currentFromClause = getWalker().getCurrentFromClause();

		if ( getWalker().getStatementType() != SqlTokenTypes.SELECT && indexed && classAlias == null ) {
			// should indicate that we are processing an INSERT/UPDATE/DELETE
			// query with a subquery implied via a collection property
			// function. Here, we need to use the table name itself as the
			// qualification alias.
			// TODO : verify this works for all databases...
			// TODO : is this also the case in non-"indexed" scenarios?
			String alias = getLhs().getFromElement().getQueryable().getTableName();
			columns = getFromElement().toColumns( alias, propertyPath, false, true );
		}

		//We do not look for an existing join on the same path, because
		//it makes sense to join twice on the same collection role
		FromElementFactory factory = new FromElementFactory(
		        currentFromClause,
		        getLhs().getFromElement(),
		        propName,
				classAlias,
		        getColumns(),
		        implicitJoin
		);
		FromElement elem = factory.createCollection( queryableCollection, role, joinType, fetch, indexed );
		
		if ( log.isDebugEnabled() ) {
			log.debug( "dereferenceCollection() : Created new FROM element for " + propName + " : " + elem );
		}
		
		setImpliedJoin( elem );
		setFromElement( elem );	// This 'dot' expression now refers to the resulting from element.
		
		if ( isSizeProperty ) {
			elem.setText("");
			elem.setUseWhereFragment(false);
		}
		
		if ( !implicitJoin ) {
			EntityPersister entityPersister = elem.getEntityPersister();
			if ( entityPersister != null ) {
				getWalker().addQuerySpaces( entityPersister.getQuerySpaces() );
			}
		}
		getWalker().addQuerySpaces( queryableCollection.getCollectionSpaces() );	// Always add the collection's query spaces.
	}

	private void dereferenceEntity(EntityType entityType, boolean implicitJoin, String classAlias, boolean generateJoin, AST parent) throws SemanticException {
		checkForCorrelatedSubquery( "dereferenceEntity" );
		// If this is an entity inside a component reference, then generate the join.
//		if ( unresolvedComponent( generateJoin ) ) {
//			if ( log.isDebugEnabled() ) {
//				log.debug( "dereferenceEntity() : resolving unresolved component '" + propertyPath + "' ... " );
//			}
//			dereferenceEntityJoin( classAlias, entityType, implicitJoin, parent );
//			return;
//		}

		// Only join to the entity table if:
		//      1) we were instructed to generate any needed joins (generateJoins==true)
		//    AND
		//      2) EITHER:
		//          A) our parent represents a further dereference of this entity to anything
		//              other than the entity's id property
		//        OR
		//          B) this node is in any clause, other than the select clause (unless that
		//              select clause is part of a scalar query :/ )
		DotNode parentAsDotNode = null;
		String property = propertyName;
		boolean joinIsNeeded = false;

		if ( isDotNode( parent ) ) {
			parentAsDotNode = ( DotNode ) parent;
			property = parentAsDotNode.propertyName;
			joinIsNeeded = generateJoin && !isReferenceToPrimaryKey( parentAsDotNode.propertyName, entityType );
		}
		else {
			joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -