/*
* Copyright (c) 2007 Genome Research Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License or
* (at your option) any later version.
*
* 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; see the file COPYING.LIB. If not, write to
* the Free Software Foundation Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307 USA
*/
package org.genedb.querying.core;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
//import org.hibernate.validator.ClassValidator;
//import org.hibernate.validator.InvalidValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Configurable
public abstract class HqlQuery implements PagedQuery {
private static final Logger logger = Logger.getLogger(HqlQuery.class);
@Autowired
protected SessionFactory sessionFactory;
protected String name;
private int order;
private static final int MAX_RESULTS = 100000;
private int maxResults = MAX_RESULTS;
/**
* Size of result retrieved
*/
protected boolean isActualResultSizeSameAsMax;
protected static final String RESTRICT_TO_TRANSCRIPTS_ONLY = " and f.type.name in ('mRNA', 'rRNA', 'scRNA', 'snoRNA', 'snRNA', 'snRNA', 'transcript', 'tRNA')";
protected static final String RESTRICT_TO_TRANSCRIPTS_AND_PSEUDOGENES = " and f.type.name in ('mRNA', 'rRNA', 'scRNA', 'snoRNA', 'snRNA', 'snRNA', 'transcript', 'tRNA', 'pseudogenic_transcript')";
protected static final String RESTRICT_TO_TRANSCRIPTS_AND_PSEUDOGENES_AND_POLYPEPTIDES = " and f.type.name in ('mRNA', 'rRNA', 'scRNA', 'snoRNA', 'snRNA', 'snRNA', 'transcript', 'tRNA', 'pseudogenic_transcript', 'polypeptide')";
//private List<CachedParamDetails> cachedParamDetailsList = new ArrayList<CachedParamDetails>();
//private Map<String, CachedParamDetails> cachedParamDetailsMap = new HashMap<String, CachedParamDetails>();
protected String featureSelector = "f.uniqueName";
protected String countSelector = "count(*)";
public String getParseableDescription() {
return QueryUtils.makeParseableDescription(name, getParamNames(), this);
}
@Override
public List<String> getResults() throws QueryException {
Session session = SessionFactoryUtils.doGetSession(sessionFactory, false);
Map<String,String> map = new HashMap<String,String>();
map.put("ORGANISM", getOrganismHql());
map.put("SELECTOR", featureSelector);
map.put("ORDERBY", getOrderBy());
String hql = restrictQuery(getHql(), map);
org.hibernate.Query query = session.createQuery(hql);
populateQueryWithParams(query);
logger.debug(query.getQueryString());
//Run query
List<String> ret = query.setMaxResults(maxResults).list();
//Get the result size
if (ret!= null && getMaxResults()==ret.size()){
isActualResultSizeSameAsMax = true;
}
return ret;
}
@Override
public List<String> getResults(int start, int end) throws QueryException {
Session session = SessionFactoryUtils.doGetSession(sessionFactory, false);
Map<String,String> map = new HashMap<String,String>();
map.put("ORGANISM", getOrganismHql());
map.put("SELECTOR", featureSelector);
map.put("ORDERBY", getOrderBy());
String hql = restrictQuery(getHql(), map);
org.hibernate.Query query = session.createQuery(hql);
populateQueryWithParams(query);
logger.debug(query.getQueryString());
//int start = page * length;
logger.info(getQueryName() + " getResults() paging " + start + "-" + end);
//Run query
@SuppressWarnings("unchecked")
List<String> ret = query.setFirstResult(start).setMaxResults(end-start+1).list();
//Get the result size
if (ret!= null && getMaxResults()==ret.size()){
isActualResultSizeSameAsMax = true;
}
return ret;
}
@Override
public int getTotalResultsSize() {
Session session = SessionFactoryUtils.doGetSession(sessionFactory, false);
Map<String,String> map = new HashMap<String,String>();
map.put("ORGANISM", getOrganismHql());
map.put("SELECTOR", countSelector);
map.put("ORDERBY", "");// we don't use order by here
String hql = restrictQuery(getHql(), map);
org.hibernate.Query query = session.createQuery(hql);
populateQueryWithParams(query);
logger.debug(query.getQueryString());
long longCount = (Long) query.uniqueResult();
if (longCount < Integer.MIN_VALUE || longCount > Integer.MAX_VALUE) {
throw new IllegalArgumentException(longCount + " cannot be cast to int without changing its value.");
}
int count = (int) longCount;
logger.info(String.format("%d == %d", longCount, count));
return count;
}
@Override
public boolean isMaxResultsReached() {
return isActualResultSizeSameAsMax;
}
protected String restrictQuery(String hql, Map<String,String> map) {
for (String key : map.keySet()) {
String val = map.get(key);
if (val == null)
continue;
hql = hql.replace("@" + key + "@", val);
}
return hql;
}
protected String restrictQueryByOrganism(String hql, String organismClause) {
if (!StringUtils.hasLength(organismClause)) {
return hql.replace("@ORGANISM@", "");
}
return hql.replace("@ORGANISM@", organismClause);
}
protected abstract void populateQueryWithParams(org.hibernate.Query query);
protected abstract String getHql();
protected abstract String getOrganismHql();
protected abstract String[] getParamNames();
protected abstract String getOrderBy();
public List<HtmlFormDetails> getFormDetails() {
List<HtmlFormDetails> ret = new ArrayList<HtmlFormDetails>();
for (String name : getParamNames()) {
HtmlFormDetails htd = new HtmlFormDetails();
//htd.setName(name);
//htd.setDefaultValue
}
return ret;
}
public Map<String, Object> prepareModelData() {
return Collections.emptyMap();
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
//@Override
public void validate(Object target, Errors errors) {
//@SuppressWarnings("unchecked") T query = (T) target;
//ClassValidator queryValidator = new ClassValidator(this.getClass());
//InvalidValue[] invalids = queryValidator.getInvalidValues(target);
//for (InvalidValue invalidValue: invalids){
// errors.rejectValue(invalidValue.getPropertyPath(), null, invalidValue.getMessage());
//}
//extraValidation(errors);
}
protected abstract void extraValidation(Errors errors);
//@Override
@SuppressWarnings("unchecked")
public boolean supports(Class clazz) {
return this.getClass().isAssignableFrom(clazz);
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
}