package no.niths.infrastructure;
import java.util.GregorianCalendar;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* This is a dynamic query generator that creates where queries based on
* provided column name and given criteria
*
*
* @param <T>
*/
public class QueryGenerator<T> {
private static final String START_TIME = "startTime";
private final String SPLITT = ",";
private Class<T> persistentClass;
private Logger logger = LoggerFactory.getLogger(QueryGenerator.class);
public QueryGenerator(Class<T> persistentClass) {
setPersistentClass(persistentClass);
}
@SuppressWarnings("unchecked")
public List<T> whereQuery(String criteria, String columnName,
Session session) {
Criteria crit = session.createCriteria(persistentClass);
crit.add(criterionBuilder(splittingCriteria(criteria), columnName));
return crit.list();
}
/**
*
* @param startTime
* @param endTime
* @param session
* @return
*/
@SuppressWarnings("unchecked")
public List<T> getBetweenDates(GregorianCalendar startTime,
GregorianCalendar endTime,Session session) {
Criteria crit = session.createCriteria(persistentClass);
boolean isEndTimeNull = endTime == null;
if (isEndTimeNull) {
crit.add(Restrictions.ge(START_TIME, startTime));
} else if (startTime != null){
crit.add(Restrictions.between(START_TIME, startTime,endTime));
}
crit.addOrder(Order.asc(START_TIME));
logger.debug(crit.toString());
return crit.list();
}
/**
* Returns a list on when and where on tags and location between
* @param criteria
* @param columnName
* @param session
* @param lo
* @param hi
* @return
*/
@SuppressWarnings("unchecked")
public List<T> whereAndBetween(String criteria, String columnName,String secondColumnName,
Session session, GregorianCalendar lo, GregorianCalendar hi) {
Criteria crit = session.createCriteria(persistentClass);
if (hi == null) {
crit.add(Restrictions.and(criterionBuilder(splittingCriteria(criteria), columnName), Restrictions.ge(secondColumnName, lo)));
} else if (lo != null) {
crit.add(Restrictions.and(criterionBuilder(splittingCriteria(criteria), columnName), Restrictions.between(secondColumnName, lo,hi)));
}
crit.addOrder(Order.asc(START_TIME));
System.err.println(crit);
return crit.list();
}
/**
* wrapper class for the criterion
*
* @param conditionBuilder
* @param columnName
* @return
*/
private Criterion criterionBuilder(String[] conditionBuilder,
String columnName) {
int size = conditionBuilder.length;
Criterion[] criterion = new Criterion[conditionBuilder.length];
// builds criterion
cirterionBuilder(conditionBuilder, columnName, size, criterion);
return logicalExpressionBuilder(size, criterion);
}
/**
* Creates and Criterion up to 4 Criterion
* @param size
* @param criterion
* @return
*/
private Criterion logicalExpressionBuilder(int size, Criterion[] criterion) {
LogicalExpression andExp = null;
switch (size) {
case 1:
return criterion[0];
case 2:
andExp = Restrictions.and(criterion[0], criterion[1]);
break;
case 3:
andExp = Restrictions.and(criterion[0],
Restrictions.and(criterion[1], criterion[2]));
break;
case 4:
andExp = Restrictions.and(
Restrictions.and(criterion[0], criterion[1]),
Restrictions.and(criterion[2], criterion[3]));
break;
default:
throw new IllegalArgumentException("You can only split on max 4 words");
}
return andExp;
}
/**
* Builds like criterion arguments with match mode anywhere
* @param conditionBuilder
* @param columnName
* @param size
* @param criterion
*/
private void cirterionBuilder(String[] conditionBuilder, String columnName,
int size, Criterion[] criterion) {
for (int i = 0; i < size; i++) {
criterion[i] = Restrictions.like(columnName, conditionBuilder[i],
MatchMode.ANYWHERE);
}
}
/**
* Splits the given criteria into a String list
*
* @param criteria
* @return
*/
private String[] splittingCriteria(String criteria) {
String[] conditionBuilder;
if (!criteria.contains(SPLITT)) {
conditionBuilder = new String[] { criteria.trim() };
} else {
conditionBuilder = criteria.trim().split(SPLITT);
}
return conditionBuilder;
}
/**
* Gets the provided persistence class
*
* @return
*/
public Class<T> getPersistentClass() {
return persistentClass;
}
/**
* Sets the provided persistence class
*
* @param persistentClass
*/
public void setPersistentClass(Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
}