📄 pathexpressionparser.java
字号:
//$Id: PathExpressionParser.java,v 1.27.2.17 2003/11/30 12:31:12 oneovthafew Exp $package net.sf.hibernate.hql;import java.util.LinkedList;import net.sf.hibernate.MappingException;import net.sf.hibernate.QueryException;import net.sf.hibernate.collection.CollectionPropertyMapping;import net.sf.hibernate.collection.QueryableCollection;import net.sf.hibernate.persister.ClassPersister;import net.sf.hibernate.persister.PropertyMapping;import net.sf.hibernate.persister.Queryable;import net.sf.hibernate.sql.JoinFragment;import net.sf.hibernate.sql.QueryJoinFragment;import net.sf.hibernate.type.EntityType;import net.sf.hibernate.type.PersistentCollectionType;import net.sf.hibernate.type.Type;import net.sf.hibernate.util.StringHelper;/** * Parses an expression of the form foo.bar.baz and builds up an expression * involving two less table joins than there are path components. */public class PathExpressionParser implements Parser { //TODO: this class does too many things! we need a different //kind of path expression parser for each of the diffferent //ways in which path expressions can occur //We should actually rework this class to not implement Parser //and just process path expressions in the most convenient way. //The class is now way to complex! private int dotcount; private String currentName; private String currentProperty; private String oneToOneOwnerName; private QueryJoinFragment join; private String[] columns; private String collectionName; private String collectionOwnerName; private String collectionRole; private final StringBuffer componentPath = new StringBuffer(); private Type type; private final StringBuffer path = new StringBuffer(); private boolean ignoreInitialJoin; private boolean continuation; private int joinType = JoinFragment.INNER_JOIN; //default mode private boolean useThetaStyleJoin = true; private PropertyMapping currentPropertyMapping; void setJoinType(int joinType) { this.joinType = joinType; } void setUseThetaStyleJoin(boolean useThetaStyleJoin) { this.useThetaStyleJoin = useThetaStyleJoin; } private void addJoin(String table, String name, String[] rhsCols) throws QueryException { String[] lhsCols = currentColumns(); join.addJoin(table, name, lhsCols, rhsCols, joinType); } String continueFromManyToMany(Class clazz, String[] joinColumns, QueryTranslator q) throws QueryException { start(q); continuation=true; currentName = q.createNameFor(clazz); q.addType(currentName, clazz); Queryable classPersister = q.getPersister(clazz); join.addJoin( classPersister.getTableName(), currentName, joinColumns, classPersister.getIdentifierColumnNames(), joinType ); currentPropertyMapping = classPersister; return currentName; } public void ignoreInitialJoin() { ignoreInitialJoin=true; } public void token(String token, QueryTranslator q) throws QueryException { if (token!=null) path.append(token); String alias = q.getPathAlias( path.toString() ); if (alias!=null) { reset(q); //reset the dotcount (but not the path) currentName = alias; //after reset! currentPropertyMapping = q.getPropertyMapping(currentName); if (!ignoreInitialJoin) { JoinFragment ojf = q.getPathJoin( path.toString() ); join.addCondition( ojf.toWhereFragmentString() ); //after reset! // we don't need to worry about any condition in the ON clause // here (toFromFragmentString), since anything in the ON condition // is already applied to the whole query } } else if ( ".".equals(token) ) { dotcount++; } else { if ( dotcount==0 ) { if (!continuation) { if ( !q.isName(token) ) throw new QueryException("undefined alias: " + token); currentName=token; currentPropertyMapping = q.getPropertyMapping(currentName); } } else if (dotcount==1) { if (currentName!=null) { currentProperty = token; } else if (collectionName!=null) { //processCollectionProperty(token, q.getCollectionPersister(collectionRole), collectionName); continuation = false; } else { throw new QueryException("unexpected"); } } else { // dotcount>=2 // Do the corresponding RHS Type propertyType = getPropertyType(); if (propertyType==null) { throw new QueryException("unresolved property: " + path); } if ( propertyType.isComponentType() ) { dereferenceComponent(token); } else if ( propertyType.isEntityType() ) { dereferenceEntity(token, (EntityType) propertyType, q); } else if ( propertyType.isPersistentCollectionType() ) { dereferenceCollection( token, ( (PersistentCollectionType) propertyType ).getRole(), q ); } else { if (token!=null) throw new QueryException("dereferenced: " + path); } } } } private void dereferenceEntity(String propertyName, EntityType propertyType, QueryTranslator q) throws QueryException { Class entityClass = propertyType.getAssociatedClass(); Queryable memberPersister = q.getPersister(entityClass); if ( // if its "id" ClassPersister.ENTITY_ID.equals(propertyName) || ( //or its the id property name memberPersister.hasIdentifierProperty() && memberPersister.getIdentifierPropertyName().equals(propertyName) ) ) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression if (componentPath.length()>0) componentPath.append(StringHelper.DOT); componentPath.append("id"); } else { String name = q.createNameFor(entityClass); q.addType(name, entityClass); //String[] keyColNames = memberPersister.getIdentifierColumnNames(); String[] keyColNames; try { keyColNames = propertyType.getReferencedColumns( q.getFactory() ); } catch (MappingException me) { throw new QueryException(me); } addJoin( memberPersister.getTableName(), name, keyColNames ); if ( propertyType.isOneToOne() ) oneToOneOwnerName = currentName; currentName = name; currentProperty = propertyName; q.addPathAliasAndJoin( path.substring( 0, path.toString().lastIndexOf(StringHelper.DOT) ), name, join ); componentPath.setLength(0); currentPropertyMapping = memberPersister; } } private void dereferenceComponent(String propertyName) { if (propertyName!=null) { if ( componentPath.length()>0 ) componentPath.append(StringHelper.DOT); componentPath.append(propertyName); } } private void dereferenceCollection(String propertyName, String role, QueryTranslator q) throws QueryException { collectionRole = role; QueryableCollection collPersister = q.getCollectionPersister(role); String[] colNames = collPersister.getKeyColumnNames(); String name= q.createNameForCollection(role); String tableName = collPersister.getTableName(); addJoin(tableName, name, colNames); if ( collPersister.hasWhere() ) join.addCondition( collPersister.getSQLWhereString(name) ); collectionName = name; collectionOwnerName = currentName; currentName = name; currentProperty = propertyName; componentPath.setLength(0); currentPropertyMapping = new CollectionPropertyMapping(collPersister); } private String getPropertyPath() { if (currentProperty==null) { return ClassPersister.ENTITY_ID; } else { if ( componentPath.length()>0 ) { return new StringBuffer() .append(currentProperty) .append(StringHelper.DOT) .append( componentPath.toString() ) .toString(); } else { return currentProperty; } } } private PropertyMapping getPropertyMapping() { return currentPropertyMapping; } private void setType() throws QueryException { if ( currentProperty==null ) { type = getPropertyMapping().getType(); } else { type = getPropertyType(); } } protected Type getPropertyType() throws QueryException { String propertyPath = getPropertyPath(); Type propertyType = getPropertyMapping().toType(propertyPath); if (propertyType==null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -