package pl.net.bluesoft.rnd.pt.ext.jbpm.query;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.SQLQuery;
import org.jbpm.pvm.internal.history.model.HistoryTaskInstanceImpl;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.model.BpmTask;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstance;
import pl.net.bluesoft.rnd.processtool.model.QueueType;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.model.nonpersistent.MutableBpmTask;
import pl.net.bluesoft.rnd.pt.ext.jbpm.BpmTaskFactory;
/**
* Class to build main query to get bpm tasks
*
* @author Maciej Pawlak
*
*/
public class BpmTaskQuery
{
/** Normal query select to retrive entities */
private static final String LIST_QUERY = "select DISTINCT task.*, process.* ";
/** Count query select to load only number of result to memory */
private static final String COUNT_QUERY = "select count(*) ";
/** Main query to get task with correlated processes from user process queue */
public static final String GET_BPM_TASKS_QUERY =
"from pt_user_process_queue queue, jbpm4_hist_actinst task, pt_process_instance process " +
"where queue.task_id = task.htask_ and process.id = queue.process_id ";
/** Additional condition to main query to add filter for user login to who task and process are assigned */
private static final String USER_LOGIN_CONDITION = " and queue.user_login = :userLogin ";
/** Additional condition to main query to add filter for queue type */
private static final String QUEUE_TYPE_CONDITION = " and queue.queue_type in (:queueTypes) ";
/** Resuls sort order */
private static final String SORY_BY_DATE_ORDER = " order by task.start_ desc";
/** String builder to build query */
private StringBuilder queryBuilder;
private Collection<QueryParameter> queryParameters;
/** Current session */
private ProcessToolContext ctx;
/** Limit for results rows */
private int maxResultsLimit;
/** Offset for results rows, used for paged views */
private int resultsOffset;
public BpmTaskQuery(ProcessToolContext ctx)
{
this.ctx = ctx;
queryBuilder = new StringBuilder(GET_BPM_TASKS_QUERY);
queryParameters = new ArrayList<BpmTaskQuery.QueryParameter>();
this.maxResultsLimit = 0;
this.resultsOffset = 0;
}
/** Add restriction for user login to who process and task are assigned */
public void addUserLoginCondition(String userLogin)
{
addCondition(USER_LOGIN_CONDITION);
addParameter("userLogin", userLogin);
}
/** Add restriction for user login to who process and task are assigned */
public void addQueueTypeCondition(Collection<QueueType> queueTypes)
{
addCondition(QUEUE_TYPE_CONDITION);
/* Map all enumerations to string, for valid type cast in database */
Collection<String> queueTypesString = new ArrayList<String>();
for(QueueType queueType: queueTypes)
queueTypesString.add(queueType.toString());
addParameter("queueTypes", queueTypesString);
}
/** Get results count. No entities are loaded to memory using this */
public int getBpmTaskCount()
{
/* Build query */
SQLQuery query = getCountQuery();
Number resultsCount = (Number)query.uniqueResult();
return resultsCount.intValue();
}
/** Get bpm tasks from initialized query */
@SuppressWarnings("unchecked")
public List<BpmTask> getBpmTasks()
{
/* Build query */
SQLQuery query = getQuery();
/* Get query results */
List<Object[]> queueResults = query.list();
List<BpmTask> result = new ArrayList<BpmTask>();
BpmTaskFactory taskFactory = new BpmTaskFactory(ctx);
/* Every row is one queue element with jbpm task as first column and process instance as second */
for(Object[] resultRow: queueResults)
{
HistoryTaskInstanceImpl taskInstance = (HistoryTaskInstanceImpl)resultRow[0];
ProcessInstance processInstance = (ProcessInstance)resultRow[1];
/* Map process and jbpm task to system's bpm task */
BpmTask task = taskFactory.create(taskInstance, processInstance);
result.add(task);
}
return result;
}
protected void addCondition(String conditionString)
{
queryBuilder.append(conditionString);
}
protected void addParameter(String key, Object value)
{
queryParameters.add(new QueryParameter(key, value));
}
private SQLQuery getCountQuery()
{
SQLQuery query = ctx.getHibernateSession().createSQLQuery(COUNT_QUERY + queryBuilder.toString());
/* Add all parameters */
for(QueryParameter parameter: queryParameters)
{
if(parameter.getValue() instanceof Collection<?>)
query.setParameterList(parameter.getKey(), (Collection<?>)parameter.getValue());
else
query.setParameter(parameter.getKey(), parameter.getValue());
}
return query;
}
/** Build main query and add stored parameters to it */
private SQLQuery getQuery()
{
/* Add results sort order */
queryBuilder.append(SORY_BY_DATE_ORDER);
SQLQuery query = ctx.getHibernateSession().createSQLQuery(LIST_QUERY + queryBuilder.toString())
.addEntity("task", HistoryTaskInstanceImpl.class)
.addEntity("process", ProcessInstance.class);
/* Add all parameters */
for(QueryParameter parameter: queryParameters)
{
if(parameter.getValue() instanceof Collection<?>)
query.setParameterList(parameter.getKey(), (Collection<?>)parameter.getValue());
else
query.setParameter(parameter.getKey(), parameter.getValue());
}
/* Add limit for max rows count */
if(getMaxResultsLimit() > 0)
query.setMaxResults(getMaxResultsLimit());
query.setFirstResult(resultsOffset);
return query;
}
public int getMaxResultsLimit() {
return maxResultsLimit;
}
/** Sets max results limit. If equals zero, there is no limit set */
public void setMaxResultsLimit(int maxResultsLimit) {
this.maxResultsLimit = maxResultsLimit;
}
public int getResultsOffset() {
return resultsOffset;
}
public void setResultsOffset(int resultsOffset)
{
this.resultsOffset = resultsOffset;
}
/** Class which provied key-object parameter for query */
private class QueryParameter
{
private String key;
private Object value;
public QueryParameter(String key, Object value)
{
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public Object getValue() {
return value;
}
}
}