//$Id: CriteriaImpl.java,v 1.8 2004/08/18 00:28:42 oneovthafew Exp $
package org.hibernate.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.PropertyMapping;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.hibernate.transform.RootEntityResultTransformer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;
/**
* Implementation of the Criteria interface
* @author Gavin King
*/
public class CriteriaImpl implements Criteria {
private List criteria = new ArrayList();
private List orderings = new ArrayList();
private Map fetchModes = new HashMap();
private Set nonVisitedFetchModes = new HashSet();
private Map associationPathByAlias = new HashMap();
private Map aliasByAssociationPath = new HashMap();
private Map classByAlias = new HashMap();
private Map lockModes = new HashMap();
private Integer maxResults;
private Integer firstResult;
private Integer timeout;
private Integer fetchSize;
private boolean cacheable;
private String cacheRegion;
private boolean forceCacheRefresh;
private String comment;
//private Class persistentClass;
private SessionImpl session;
private ResultTransformer resultTransformer = new RootEntityResultTransformer();
private int counter=0;
private String generateAlias() {
return "x" + counter++ + '_';
}
public final class Subcriteria implements Criteria {
private String rootAlias;
private String rootPath;
private Subcriteria(String rootAlias, String rootPath) {
this.rootAlias = rootAlias;
this.rootPath = rootPath;
}
public Criteria add(Criterion expression) {
CriteriaImpl.this.add(rootAlias, expression);
return this;
}
public Criteria createAlias(String associationPath, String alias)
throws HibernateException {
CriteriaImpl.this.createAlias(rootAlias, associationPath, alias);
return this;
}
public Criteria addOrder(Order order) {
throw new UnsupportedOperationException("subcriteria cannot be ordered");
}
public Criteria setCacheable(boolean cacheable) {
CriteriaImpl.this.setCacheable(cacheable);
return this;
}
public Criteria setCacheRegion(String cacheRegion) {
CriteriaImpl.this.setCacheRegion(cacheRegion);
return this;
}
public Criteria setForceCacheRefresh(boolean forceCacheRefresh) {
CriteriaImpl.this.setForceCacheRefresh(forceCacheRefresh);
return this;
}
public Criteria createCriteria(String associationPath)
throws HibernateException {
return CriteriaImpl.this.createCriteriaAt(rootAlias, associationPath);
}
public List list() throws HibernateException {
return CriteriaImpl.this.list();
}
public ScrollableResults scroll() throws HibernateException {
return CriteriaImpl.this.scroll();
}
public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
return CriteriaImpl.this.scroll(scrollMode);
}
public Object uniqueResult() throws HibernateException {
return CriteriaImpl.this.uniqueResult();
}
public Criteria setFetchMode(String associationPath, FetchMode mode)
throws HibernateException {
CriteriaImpl.this.setFetchMode( StringHelper.qualify(rootPath, associationPath), mode);
return this;
}
public Criteria setFirstResult(int firstResult) {
CriteriaImpl.this.setFirstResult(firstResult);
return this;
}
public Criteria setMaxResults(int maxResults) {
CriteriaImpl.this.setMaxResults(maxResults);
return this;
}
public Criteria setTimeout(int timeout) {
CriteriaImpl.this.setTimeout(timeout);
return this;
}
public Criteria setFetchSize(int fetchSize) {
CriteriaImpl.this.setFetchSize(fetchSize);
return this;
}
public Class getCriteriaClass() {
return CriteriaImpl.this.getCriteriaClass(rootAlias);
}
public Class getCriteriaClass(String alias) {
return CriteriaImpl.this.getCriteriaClass(alias);
}
public String getCriteriaEntityName(String alias) {
return CriteriaImpl.this.getCriteriaEntityName(alias);
}
public String getCriteriaEntityName() {
return CriteriaImpl.this.getCriteriaEntityName(rootAlias);
}
public Criteria createCriteria(String associationPath, String alias)
throws HibernateException {
return CriteriaImpl.this.createCriteriaAt(rootAlias, associationPath, alias);
}
public Criteria returnMaps() {
CriteriaImpl.this.returnMaps();
return this;
}
public Criteria returnRootEntities() {
CriteriaImpl.this.returnRootEntities();
return this;
}
public Criteria setLockMode(LockMode lockMode) {
CriteriaImpl.this.setLockMode(rootAlias, lockMode);
return this;
}
public Criteria setLockMode(String alias, LockMode lockMode) {
CriteriaImpl.this.setLockMode(alias, lockMode);
return this;
}
public Criteria setResultTransformer(ResultTransformer resultProcessor) {
CriteriaImpl.this.setResultTransformer(resultProcessor);
return this;
}
public Criteria setComment(String comment) {
CriteriaImpl.this.setComment(comment);
return this;
}
}
public Criteria setMaxResults(int maxResults) {
this.maxResults = new Integer(maxResults);
return this;
}
public Criteria setFirstResult(int firstResult) {
this.firstResult = new Integer(firstResult);
return this;
}
public Integer getFetchSize() {
return fetchSize;
}
public Criteria setFetchSize(int fetchSize) {
this.fetchSize = new Integer(fetchSize);
return this;
}
public Criteria setTimeout(int timeout) {
this.timeout = new Integer(timeout);
return this;
}
public Criteria add(Criterion expression) {
add(Criteria.ROOT_ALIAS, expression);
return this;
}
public Integer getMaxResults() {
return maxResults;
}
public Integer getFirstResult() {
return firstResult;
}
public Integer getTimeout() {
return timeout;
}
public CriteriaImpl(String entityName, SessionImpl session) {
//this.persistentClass = null; //TODO!!!!!!!
this.session = session;
this.classByAlias.put(Criteria.ROOT_ALIAS, entityName);
this.cacheable = false;
}
/**
* Copy all the internal attributes of the given CrtieriaImpl
* except alter the root persistent class type to be the given one.
*/
public CriteriaImpl(String entityName, CriteriaImpl original) {
this.classByAlias = original.classByAlias;
this.classByAlias.put(Criteria.ROOT_ALIAS, entityName);
this.criteria = original.criteria;
this.orderings = original.orderings;
this.fetchModes = original.fetchModes;
this.nonVisitedFetchModes = original.nonVisitedFetchModes;
this.associationPathByAlias = original.associationPathByAlias;
this.aliasByAssociationPath = original.aliasByAssociationPath;
this.lockModes = original.lockModes;
this.maxResults = original.maxResults;
this.firstResult = original.firstResult;
this.timeout = original.timeout;
this.fetchSize = original.fetchSize;
this.session = original.session;
this.resultTransformer = original.resultTransformer;
this.counter = original.counter;
this.cacheable = original.cacheable;
this.cacheRegion = original.cacheRegion;
this.comment = original.comment;
}
public List list() throws HibernateException {
return session.find(this);
}
public ScrollableResults scroll() {
return session.scroll(this, ScrollMode.SCROLL_INSENSITIVE);
}
public ScrollableResults scroll(ScrollMode scrollMode) {
return session.scroll(this, scrollMode);
}
void checkFetchModes() {
if(! nonVisitedFetchModes.isEmpty()) {
throw new QueryException("Invalid path : " + (String) nonVisitedFetchModes.iterator().next());
}
}
public boolean getCacheable() {
return this.cacheable;
}
public String getCacheRegion() {
return this.cacheRegion;
}
public Criteria setCacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
public Criteria setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion.trim();
return this;
}
public Iterator iterateExpressionEntries() {
return criteria.iterator();
}
public Iterator iterateOrderings() {
return orderings.iterator();
}
public Map getAliasClasses() {
return classByAlias;
}
public String toString() {
return "CriteriaImpl(" + getCriteriaEntityName() + criteria.toString() + ')';
}
public Criteria addOrder(Order ordering) {
orderings.add(ordering);
return this;
}
public FetchMode getFetchMode(String path) {
nonVisitedFetchModes.remove(path);
return (FetchMode) fetchModes.get(path);
}
public Criteria setFetchMode(String associationPath, FetchMode mode) {
fetchModes.put(associationPath, mode);
nonVisitedFetchModes.add(associationPath);
return this;
}
public Criteria createAlias(String associationPath, String alias) throws HibernateException {
createAlias(ROOT_ALIAS, associationPath, alias);
return this;
}
private void createAlias(String rootAlias, String associationPath, String alias) throws HibernateException {
String testAlias = StringHelper.root(associationPath);
if ( classByAlias.containsKey(testAlias) ) {
rootAlias = testAlias;
associationPath = associationPath.substring( rootAlias.length() + 1 );
}
String rootPath = (String) associationPathByAlias.get(rootAlias);
String wholeAssociationPath;
if (rootPath==null) {
if ( !ROOT_ALIAS.equals(rootAlias) ) throw new HibernateException("unknown alias: " + rootAlias);
wholeAssociationPath = associationPath;
}
else {
wholeAssociationPath = StringHelper.qualify(rootPath, associationPath);
}
Object oldPath = associationPathByAlias.put(alias, wholeAssociationPath);
if (oldPath!=null) throw new HibernateException("alias already defined: " + alias);
Object oldAlias = aliasByAssociationPath.put(wholeAssociationPath, alias);
if (oldAlias!=null) throw new HibernateException("association already joined: " + wholeAssociationPath);
classByAlias.put( alias, getClassForPath(rootAlias, associationPath) );
}
public boolean isJoin(String path) {
return aliasByAssociationPath.containsKey(path);
}
public String getAlias(String associationPath) {
return (String) aliasByAssociationPath.get(associationPath);
}
public Criteria add(String alias, Criterion expression) {
criteria.add( new CriterionEntry(expression, alias) );
return this;
}
/*private Type getType(PropertyMapping pm, String associationPath, SessionFactoryImplementor factory)
throws HibernateException {
//whoa! reuseable code buried all the way down here!
String[] pathComponents = StringHelper.split(".", associationPath);
StringBuffer subpath = new StringBuffer( associationPath.length() );
Type type = null;
for ( int i=0; i