[jbpm-commits] JBoss JBPM SVN: r6748 - in jbpm4/trunk/modules: pvm/src/main/java/org/jbpm/pvm/internal/hibernate and 9 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Oct 8 05:26:00 EDT 2010


Author: rebody
Date: 2010-10-08 05:25:57 -0400 (Fri, 08 Oct 2010)
New Revision: 6748

Added:
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryCondition.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryProperty.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/QuerySession.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/OptimisticLockException.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding/QuerySessionBinding.java
Modified:
   jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/QueryOperator.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/DbSessionImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AvgDurationPerActivityQueryCmd.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ChoiceDistributionQueryCmd.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryActivityInstanceQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryDetailQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryProcessInstanceQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/ProcessDeployer.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/DbSession.java
   jbpm4/trunk/modules/pvm/src/main/resources/jbpm.default.cfg.xml
   jbpm4/trunk/modules/pvm/src/main/resources/jbpm.wire.bindings.xml
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/forkjoin/ForkResultsInNullEndActivityTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryActivityInstanceQueryTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryProcessInstanceQueryTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/ProcessInstanceQueryTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/TaskQueryTest.java
Log:
JBPM-2927 move hibernate package from *Query to QuerySession.

Modified: jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/QueryOperator.java
===================================================================
--- jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/QueryOperator.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/QueryOperator.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -3,10 +3,27 @@
 public enum QueryOperator {
 
   EQUALS("="),
+
+  NOT_EQUALS("!="),
+
+  GREATER_THAN(">"),
+
+  GREATER_THAN_OR_EQUAL(">="),
+
+  LESS_THAN("<"),
+
+  LESS_THAN_OR_EQUAL("<="),
+
   LIKE("like"),
+
   IN("in"),
-  NOT_IN("not in");
 
+  NOT_IN("not in"),
+
+  IS_NULL("is null"),
+
+  NOT_NULL("is not null");
+
   private final String value;
 
   QueryOperator(String value) {

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/DbSessionImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/DbSessionImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/DbSessionImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -24,8 +24,10 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.hibernate.Criteria;
@@ -608,4 +610,51 @@
         .setReadOnly(true)
         .list();
   }
+
+  // query
+  public Map<String, Number> findAvgDurationPerActivity(String processDefinitionId) {
+    List<?> results = session
+      .createQuery("select hai.activityName, avg(hai.duration) "
+        + "from "
+        + HistoryActivityInstanceImpl.class.getName()
+        + " as hai "
+        + "where hai.historyProcessInstance.processDefinitionId = :processDefinitionId "
+        + "group by hai.activityName")
+      .setString("processDefinitionId", processDefinitionId)
+      .list();
+
+    Map<String, Number> avgDurationPerActivity = new HashMap<String, Number>();
+    for (Object result: results) {
+      Object[] pair = (Object[]) result;
+      avgDurationPerActivity.put((String) pair[0], (Number) pair[1]);
+    }
+
+    return avgDurationPerActivity;
+  }
+
+  public Map<String, Number> findChoiceDistribution(String processDefinitionId, String activityName) {
+    List<?> results = session
+      .createQuery("select hai.transitionName, count(hai) "
+        + "from "
+        + HistoryActivityInstanceImpl.class.getName()
+        + " as hai "
+        + "where hai.historyProcessInstance.processDefinitionId = :processDefinitionId "
+        + "  and hai.activityName = :activityName "
+        + "group by hai.transitionName")
+      .setString("processDefinitionId", processDefinitionId)
+      .setString("activityName", activityName)
+      .list();
+
+    Map<String, Number> choiceDistributionCounts = new HashMap<String, Number>();
+
+    for (Object result : results) {
+      Object[] pair = (Object[]) result;
+      String transitionName = (String) pair[0];
+      Number number = (Number) pair[1];
+
+      choiceDistributionCounts.put(transitionName, number);
+    }
+
+    return choiceDistributionCounts;
+  }
 }

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,638 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.hibernate;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jbpm.api.Deployment;
+import org.jbpm.api.ProcessDefinition;
+import org.jbpm.api.QueryOperator;
+import org.jbpm.api.identity.Group;
+import org.jbpm.internal.log.Log;
+import org.jbpm.pvm.internal.env.EnvironmentImpl;
+import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;
+import org.jbpm.pvm.internal.history.model.HistoryCommentImpl;
+import org.jbpm.pvm.internal.history.model.HistoryDetailImpl;
+import org.jbpm.pvm.internal.history.model.HistoryProcessInstanceImpl;
+import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
+import org.jbpm.pvm.internal.history.model.HistoryTaskInstanceImpl;
+import org.jbpm.pvm.internal.identity.spi.IdentitySession;
+import org.jbpm.pvm.internal.job.JobImpl;
+import org.jbpm.pvm.internal.job.MessageImpl;
+import org.jbpm.pvm.internal.job.TimerImpl;
+import org.jbpm.pvm.internal.model.ExecutionImpl;
+import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
+import org.jbpm.pvm.internal.query.QueryCondition;
+import org.jbpm.pvm.internal.query.QueryProperty;
+import org.jbpm.pvm.internal.session.QuerySession;
+import org.jbpm.pvm.internal.session.RepositorySession;
+import org.jbpm.pvm.internal.repository.DeploymentImpl;
+import org.jbpm.pvm.internal.repository.DeploymentProperty;
+import org.jbpm.pvm.internal.task.TaskImpl;
+import org.jbpm.pvm.internal.task.ParticipationImpl;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+/**
+ * query session implementation for hibernate.
+ *
+ * @author Huisheng Xu
+ */
+public class QuerySessionImpl implements QuerySession {
+
+    private static Log log = Log.getLog(QuerySessionImpl.class.getName());
+
+    protected Session session;
+
+    public Object query(QueryProperty queryProperty) {
+        if (DeploymentImpl.class.getName().equals(queryProperty.getKey())
+                || ExecutionImpl.class.getName().equals(queryProperty.getKey())
+                || JobImpl.class.getName().equals(queryProperty.getKey())
+                || MessageImpl.class.getName().equals(queryProperty.getKey())
+                || TimerImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryDefault(queryProperty);
+        } else if (TaskImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryTask(queryProperty);
+        } else if (ProcessDefinitionImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryProcessDefinition(queryProperty);
+        } else if (HistoryActivityInstanceImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryHistoryActivityInstance(queryProperty);
+        } else if (HistoryDetailImpl.class.getName().equals(queryProperty.getKey())
+                || HistoryCommentImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryHistoryDetail(queryProperty);
+        } else if (HistoryProcessInstanceImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryHistoryProcessInstance(queryProperty);
+        } else if (HistoryTaskImpl.class.getName().equals(queryProperty.getKey())) {
+            return queryHistoryTask(queryProperty);
+        }
+        log.error("cannot handle [" + queryProperty.getKey() + "]");
+        return null;
+    }
+
+    protected Object queryDefault(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+        String key = queryProperty.getKey();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(*) from ")
+                .append(key);
+        } else {
+            buff.append("from ")
+                .append(key);
+        }
+
+        // where
+        Map params = new HashMap();
+        this.appendWhereClause(buff, queryProperty, params, false);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    protected Object queryTask(QueryProperty queryProperty) {
+        if (queryProperty.hasCondition("candidate")) {
+            return queryTaskWithParticipant(queryProperty);
+        } else {
+            return queryTaskWithoutParticipant(queryProperty);
+        }
+    }
+
+    protected Object queryTaskWithParticipant(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(distinct task.id) from ")
+                .append(ParticipationImpl.class.getName())
+                .append(" as participant join participant.task as task ");
+        } else {
+            buff.append("select distinct task.id from ")
+                .append(ParticipationImpl.class.getName())
+                .append(" as participant join participant.task as task ");
+        }
+        buff.append("where participant.type = 'candidate'");
+
+        IdentitySession identitySession = EnvironmentImpl.getFromCurrent(IdentitySession.class);
+
+        String candidate = (String) queryProperty.getCondition("candidate").getValue();
+        List<Group> groups = identitySession.findGroupsByUser(candidate);
+
+        if (log.isDebugEnabled()) {
+            log.debug("setting parameter candidateUserId: " + candidate);
+        }
+
+        Map params = new HashMap();
+
+        if (groups.isEmpty()) {
+            buff.append(" and participant.userId = :candidateUserId ");
+            params.put("candidateUserId", candidate);
+        } else {
+            List<String> groupIds = new ArrayList<String>();
+            for (Group group : groups) {
+              groupIds.add(group.getId());
+            }
+
+            if (log.isDebugEnabled()) {
+                log.debug("setting parameter candidateGroupIds: " + groupIds);
+            }
+
+            buff.append(" and (participant.userId = :candidateUserId or participant.groupId in (:candidateGroupIds))");
+            params.put("candidateUserId", candidate);
+            params.put("candidateGroupIds", groupIds);
+        }
+
+        queryProperty.removeCondition("candidate");
+
+        this.appendWhereClause(buff, queryProperty, params, true);
+
+        Object result = this.executeQuery(buff.toString(), params, queryProperty);
+
+        // in order to solve duplicated records in oracle.
+
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_UNIQUE) {
+            if (result == null) {
+                return null;
+            } else {
+                return session.get(TaskImpl.class, (Serializable) result);
+            }
+        } else if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            return result;
+        }
+
+        List<Long> taskIds = (List<Long>) result;
+        if (taskIds.isEmpty()) {
+            return Collections.EMPTY_LIST;
+        }
+
+        buff = new StringBuilder();
+
+        buff.append("from ")
+            .append(TaskImpl.class.getName())
+            .append(" task where task.id in (:taskIds)");
+
+        this.appendOrderClause(buff, queryProperty);
+
+        return session.createQuery(buff.toString())
+            .setParameterList("taskIds", taskIds)
+            .list();
+    }
+
+    protected Object queryTaskWithoutParticipant(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(task.id) from ")
+                .append(TaskImpl.class.getName())
+                .append(" as task ");
+        } else {
+            buff.append("from ")
+                .append(TaskImpl.class.getName())
+                .append(" as task ");
+        }
+
+        Map params = new HashMap();
+        this.appendWhereClause(buff, queryProperty, params, false);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    protected Object queryProcessDefinition(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+
+        // select, from
+        buff.append("select new map(idProperty.objectName as objectName,")
+            .append("idProperty.deployment.dbid as deploymentDbid) ")
+            .append("from ")
+            .append(DeploymentImpl.class.getName())
+            .append(" as deployment, ")
+            .append(DeploymentProperty.class.getName())
+            .append(" as idProperty, ")
+            .append(DeploymentProperty.class.getName())
+            .append(" as keyProperty, ")
+            .append(DeploymentProperty.class.getName())
+            .append(" as versionProperty ");
+
+        // where
+        buff.append("where idProperty.key = '" + DeploymentImpl.KEY_PROCESS_DEFINITION_ID + "' ")
+            .append("and idProperty.deployment = deployment ")
+            .append("and keyProperty.key = '" + DeploymentImpl.KEY_PROCESS_DEFINITION_KEY + "' ")
+            .append("and keyProperty.objectName = idProperty.objectName ")
+            .append("and keyProperty.deployment = deployment ")
+            .append("and versionProperty.key = '" + DeploymentImpl.KEY_PROCESS_DEFINITION_VERSION + "' ")
+            .append("and versionProperty.objectName = idProperty.objectName ")
+            .append("and versionProperty.deployment = deployment ");
+
+        Map params = new HashMap();
+        this.appendWhereClause(buff, queryProperty, params, true);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        String hql = buff.toString();
+        log.debug(hql);
+
+        RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class);
+
+        Query query = session.createQuery(hql).setProperties(params);
+
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE_UNIQUE
+                || queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE_COUNT) {
+             query.setFirstResult(queryProperty.getFirstResult())
+                  .setMaxResults(queryProperty.getMaxResults());
+        }
+
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_UNIQUE
+                || queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE_UNIQUE) {
+            Object result = query.uniqueResult();
+            if (result == null) {
+                return null;
+            }
+            return getProcessDefinition(repositorySession, result);
+        } else {
+            Object result = query.list();
+            List<?> propertyMaps = (List<?>) result;
+            if (propertyMaps.isEmpty()) {
+                return Collections.EMPTY_LIST;
+            }
+
+            List<ProcessDefinition> processDefinitions = new ArrayList<ProcessDefinition>();
+            for (Object propertyObject : propertyMaps) {
+                ProcessDefinitionImpl processDefinition = getProcessDefinition(repositorySession, propertyObject);
+                processDefinitions.add(processDefinition);
+            }
+            return processDefinitions;
+        }
+    }
+
+    protected Object queryHistoryActivityInstance(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+        String key = queryProperty.getKey();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(*) from ")
+                .append(key);
+        } else {
+            buff.append("from ")
+                .append(key);
+        }
+
+        // where
+        Map params = new HashMap();
+        boolean alreadyAddWhere = false;
+
+        if (queryProperty.hasCondition("tookLessThen")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("duration<:tookLessThen");
+            params.put("tookLessThen", queryProperty.getCondition("tookLessThen").getValue());
+            queryProperty.removeCondition("tookLessThen");
+        }
+
+        if (queryProperty.hasCondition("tookLongerThen")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("duration>:tookLongerThen");
+            params.put("tookLongerThen", queryProperty.getCondition("tookLongerThen").getValue());
+            queryProperty.removeCondition("tookLongerThen");
+        }
+
+        if (queryProperty.hasCondition("startedBefore")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("startTime<:startedBefore");
+            params.put("startedBefore", queryProperty.getCondition("startedBefore").getValue());
+            queryProperty.removeCondition("startedBefore");
+        }
+
+        if (queryProperty.hasCondition("startedAfter")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("startTime>:startedAfter");
+            params.put("startedAfter", queryProperty.getCondition("startedAfter").getValue());
+            queryProperty.removeCondition("startedAfter");
+        }
+
+        this.appendWhereClause(buff, queryProperty, params, alreadyAddWhere);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    protected Object queryHistoryDetail(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+        String key = queryProperty.getKey();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(*) from ")
+                .append(key);
+        } else {
+            buff.append("from ")
+                .append(key);
+        }
+
+        // where
+        Map params = new HashMap();
+        boolean alreadyAddWhere = false;
+
+        if (queryProperty.hasCondition("timeBefore")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("startTime<:timeBefore");
+            params.put("timeBefore", queryProperty.getCondition("timeBefore").getValue());
+            queryProperty.removeCondition("timeBefore");
+        }
+
+        if (queryProperty.hasCondition("timeAfter")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("startTime>:timeAfter");
+            params.put("timeAfter", queryProperty.getCondition("timeAfter").getValue());
+            queryProperty.removeCondition("timeAfter");
+        }
+
+        this.appendWhereClause(buff, queryProperty, params, alreadyAddWhere);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    protected Object queryHistoryProcessInstance(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+        String key = queryProperty.getKey();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(*) from ")
+                .append(key);
+        } else {
+            buff.append("from ")
+                .append(key);
+        }
+
+        // where
+        Map params = new HashMap();
+        boolean alreadyAddWhere = false;
+
+        if (queryProperty.hasCondition("endedBefore")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("endTime<:endedBefore");
+            params.put("endedBefore", queryProperty.getCondition("endedBefore").getValue());
+            queryProperty.removeCondition("endedBefore");
+        }
+
+        if (queryProperty.hasCondition("endedAfter")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("endTime>=:endedAfter");
+            params.put("endedAfter", queryProperty.getCondition("endedAfter").getValue());
+            queryProperty.removeCondition("endedAfter");
+        }
+
+        this.appendWhereClause(buff, queryProperty, params, alreadyAddWhere);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    protected Object queryHistoryTask(QueryProperty queryProperty) {
+        StringBuilder buff = new StringBuilder();
+        String key = queryProperty.getKey();
+
+        // select, from
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT) {
+            buff.append("select count(ht) from ")
+                .append(key)
+                .append(" as ht");
+        } else {
+            buff.append("select ht from ")
+                .append(key)
+                .append(" as ht");
+        }
+
+        // where
+        Map params = new HashMap();
+        boolean alreadyAddWhere = false;
+
+        if (queryProperty.hasCondition("processInstanceId")) {
+            buff.append(", ")
+                .append(HistoryTaskInstanceImpl.class.getName())
+                .append(" as hti ")
+                .append(" where ht=hti.historyTask")
+                .append(" and hti.historyProcessInstance.processInstanceId=:processInstanceId");
+            alreadyAddWhere = true;
+            params.put("processInstanceId", queryProperty.getCondition("processInstanceId").getValue());
+            queryProperty.removeCondition("processInstanceId");
+        }
+
+        if (queryProperty.hasCondition("tookLessThen")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("ht.duration<:tookLessThen");
+            params.put("tookLessThen", queryProperty.getCondition("tookLessThen").getValue());
+            queryProperty.removeCondition("tookLessThen");
+        }
+
+        if (queryProperty.hasCondition("tookLongerThen")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("ht.duration>:tookLongerThen");
+            params.put("tookLongerThen", queryProperty.getCondition("tookLongerThen").getValue());
+            queryProperty.removeCondition("tookLongerThen");
+        }
+
+        if (queryProperty.hasCondition("startedBefore")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("ht.createTime<:startedBefore");
+            params.put("startedBefore", queryProperty.getCondition("startedBefore").getValue());
+            queryProperty.removeCondition("startedBefore");
+        }
+
+        if (queryProperty.hasCondition("startedAfter")) {
+            if (alreadyAddWhere) {
+                buff.append(" and ");
+            } else {
+                buff.append(" where ");
+                alreadyAddWhere = true;
+            }
+            buff.append("ht.createTime>:startedAfter");
+            params.put("startedAfter", queryProperty.getCondition("startedAfter").getValue());
+            queryProperty.removeCondition("startedAfter");
+        }
+
+        this.appendWhereClause(buff, queryProperty, params, alreadyAddWhere);
+
+        // order by
+        this.appendOrderClause(buff, queryProperty);
+
+        return this.executeQuery(buff.toString(), params, queryProperty);
+    }
+
+    // ~ ======================================================================
+
+    protected void appendWhereClause(StringBuilder buff, QueryProperty queryProperty, Map params, boolean originalAlreadyAddWhere) {
+        // where
+        boolean alreadyAddWhere = originalAlreadyAddWhere;
+        for (Map.Entry<String, QueryCondition> entry : queryProperty.getConditions().entrySet()) {
+            QueryCondition queryCondition = entry.getValue();
+            if (!alreadyAddWhere) {
+                alreadyAddWhere = true;
+                buff.append(" where ");
+            } else {
+                buff.append(" and ");
+            }
+
+            String fieldName = entry.getKey();
+            String varName = fieldName.replaceAll("\\.", "_");
+            buff.append(fieldName)
+                .append(" ")
+                .append(queryCondition.getOperator());
+
+            if (queryCondition.getOperator() == QueryOperator.IN
+                    || queryCondition.getOperator() == QueryOperator.NOT_IN) {
+                buff.append("(:")
+                    .append(varName)
+                    .append(")");
+                params.put(varName, queryCondition.getValue());
+            } else if (queryCondition.getOperator() == QueryOperator.IS_NULL
+                    || queryCondition.getOperator() == QueryOperator.NOT_NULL) {
+            } else {
+                buff.append(" :")
+                    .append(varName);
+                params.put(varName, queryCondition.getValue());
+            }
+        }
+    }
+
+    protected void appendOrderClause(StringBuilder buff, QueryProperty queryProperty) {
+        // order by
+        boolean alreadyAddOrder = false;
+        for (Map.Entry<String, String> entry : queryProperty.getOrders().entrySet()) {
+            if (!alreadyAddOrder) {
+                alreadyAddOrder = true;
+                buff.append(" order by ");
+            } else {
+                buff.append(",");
+            }
+
+            buff.append(entry.getKey())
+                .append(" ")
+                .append(entry.getValue());
+        }
+    }
+
+    protected Object executeQuery(String hql, Map<String, Object> params, QueryProperty queryProperty) {
+        log.debug(hql);
+
+        Query query = session.createQuery(hql);
+        query.setProperties(params);
+
+        if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE) {
+             return query.setFirstResult(queryProperty.getFirstResult())
+                         .setMaxResults(queryProperty.getMaxResults())
+                         .list();
+        } else if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE_UNIQUE
+                || queryProperty.getResultType() == QueryProperty.RESULT_TYPE_PAGE_COUNT) {
+             return query.setFirstResult(queryProperty.getFirstResult())
+                         .setMaxResults(queryProperty.getMaxResults())
+                         .uniqueResult();
+        } else if (queryProperty.getResultType() == QueryProperty.RESULT_TYPE_COUNT
+                || queryProperty.getResultType() == QueryProperty.RESULT_TYPE_UNIQUE) {
+            return query.uniqueResult();
+        } else {
+            return query.list();
+        }
+    }
+
+    private static ProcessDefinitionImpl getProcessDefinition(RepositorySession repositorySession, Object propertyObject) {
+        Map<?, ?> propertyMap = (Map<?, ?>) propertyObject;
+        String deploymentId = propertyMap.get("deploymentDbid").toString();
+        String objectName = (String)propertyMap.get("objectName");
+        return (ProcessDefinitionImpl) repositorySession.getObject(deploymentId, objectName);
+    }
+}

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -28,18 +28,18 @@
 import java.util.List;
 import java.util.Map;
 
-import org.hibernate.Query;
-import org.hibernate.Session;
 import org.jbpm.api.JbpmException;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.cmd.Command;
 import org.jbpm.api.cmd.Environment;
 import org.jbpm.pvm.internal.cmd.CommandService;
 import org.jbpm.pvm.internal.env.EnvironmentImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 
 /**
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public abstract class AbstractQuery implements Command<Object> {
 
@@ -54,24 +54,24 @@
 
   protected Map<String, QueryOperator> parameterOperators = new HashMap<String, QueryOperator>();
 
-  protected abstract void applyParameters(Query query);
-
-  protected abstract String hql();
-
   /* reuse by copy and paste:
    * (return type can't be changed)
   public ConcreteQuery page(int firstResult, int maxResults) {
     this.page = new Page(firstResult, maxResults);
     return this;
-  } 
+  }
   */
 
   public List<?> untypedList() {
     if (commandService != null) {
       return (List<?>) commandService.execute(this);
     }
-    Session session = EnvironmentImpl.getFromCurrent(Session.class);
-    return (List<?>) execute(session);
+    QuerySession querySession = EnvironmentImpl.getFromCurrent(QuerySession.class);
+    try {
+      return (List<?>) execute(querySession);
+    } catch(Exception ex) {
+      throw new JbpmException(ex);
+    }
   }
 
   protected Object untypedUniqueResult() {
@@ -80,27 +80,23 @@
     if (commandService != null) {
       return commandService.execute(this);
     }
-    Session session = EnvironmentImpl.getFromCurrent(Session.class);
-    return execute(session);
+    QuerySession querySession = EnvironmentImpl.getFromCurrent(QuerySession.class);
+    try {
+      return execute(querySession);
+    } catch(Exception ex) {
+      throw new JbpmException(ex);
+    }
   }
 
-  public Object execute(Environment environment) throws Exception {
-    Session session = environment.get(Session.class);
+  public Object execute(Environment env) throws Exception {
+    QuerySession querySession = env.get(QuerySession.class);
     try {
-      return execute(session);
-    }
-    finally {
+      return execute(querySession);
+    } finally {
       resetQuery(); // reset the query member fields so the query can be reused.
     }
   }
 
-  public Object execute(Session session) {
-    Query query = session.createQuery(hql());
-    applyParameters(query);
-    applyPage(query);
-    return uniqueResult ? query.uniqueResult() : query.list();
-  }
-
   /**
    * Returns the count of the query.
    * Query types that want to use this count method should
@@ -121,7 +117,7 @@
   /**
    * Resets the query so it can be reused after an invocation.
    */
-  private void resetQuery() {
+  protected void resetQuery() {
     isWhereAdded = false;
     count = false;
     uniqueResult = false;
@@ -145,13 +141,6 @@
     }
   }
 
-  protected void applyPage(Query query) {
-    if (page != null) {
-      query.setFirstResult(page.firstResult);
-      query.setMaxResults(page.maxResults);
-    }
-  }
-
   protected void addOrderByClause(String clause) {
     if (orderByClause == null) {
       orderByClause = clause;
@@ -218,19 +207,18 @@
     }
   }
 
-  protected void applyParameterWithOperator(String name, Object[] values, Query query) {
-    switch (values.length) {
-    case 0:
-      break;
-    case 1:
-      query.setParameter(name, values[0]);
-      break;
-    default:
-      query.setParameterList(name, values);
-    }
-  }
-
   public void setCommandService(CommandService commandService) {
     this.commandService = commandService;
   }
+
+  protected QueryOperator findOperator(String name) {
+    QueryOperator operator = parameterOperators.get(name);
+    if (operator == null) {
+      return QueryOperator.EQUALS;
+    } else {
+      return operator;
+    }
+  }
+
+  protected abstract Object execute(QuerySession querySession) throws Exception;
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AvgDurationPerActivityQueryCmd.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AvgDurationPerActivityQueryCmd.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AvgDurationPerActivityQueryCmd.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,15 +21,11 @@
  */
 package org.jbpm.pvm.internal.query;
 
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
-import org.hibernate.Session;
-
 import org.jbpm.api.cmd.Command;
 import org.jbpm.api.cmd.Environment;
-import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;
+import org.jbpm.pvm.internal.session.DbSession;
 
 /**
  * @author Tom Baeyens
@@ -45,22 +41,6 @@
   }
 
   public Map<String, Number> execute(Environment environment) throws Exception {
-    List<?> results = environment.get(Session.class)
-      .createQuery("select hai.activityName, avg(hai.duration) "
-        + "from "
-        + HistoryActivityInstanceImpl.class.getName()
-        + " as hai "
-        + "where hai.historyProcessInstance.processDefinitionId = :processDefinitionId "
-        + "group by hai.activityName")
-      .setString("processDefinitionId", processDefinitionId)
-      .list();
-
-    Map<String, Number> avgDurationPerActivity = new HashMap<String, Number>();
-    for (Object result: results) {
-      Object[] pair = (Object[]) result;
-      avgDurationPerActivity.put((String) pair[0], (Number) pair[1]);
-    }
-
-    return avgDurationPerActivity;
+    return environment.get(DbSession.class).findAvgDurationPerActivity(processDefinitionId);
   }
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ChoiceDistributionQueryCmd.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ChoiceDistributionQueryCmd.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ChoiceDistributionQueryCmd.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,15 +21,11 @@
  */
 package org.jbpm.pvm.internal.query;
 
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
-import org.hibernate.Session;
-
 import org.jbpm.api.cmd.Command;
 import org.jbpm.api.cmd.Environment;
-import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;
+import org.jbpm.pvm.internal.session.DbSession;
 
 /**
  * @author Tom Baeyens
@@ -47,28 +43,6 @@
   }
 
   public Map<String, Number> execute(Environment environment) {
-    List<?> results = environment.get(Session.class)
-      .createQuery("select hai.transitionName, count(hai) "
-        + "from "
-        + HistoryActivityInstanceImpl.class.getName()
-        + " as hai "
-        + "where hai.historyProcessInstance.processDefinitionId = :processDefinitionId "
-        + "  and hai.activityName = :activityName "
-        + "group by hai.transitionName")
-      .setString("processDefinitionId", processDefinitionId)
-      .setString("activityName", activityName)
-      .list();
-
-    Map<String, Number> choiceDistributionCounts = new HashMap<String, Number>();
-
-    for (Object result : results) {
-      Object[] pair = (Object[]) result;
-      String transitionName = (String) pair[0];
-      Number number = (Number) pair[1];
-
-      choiceDistributionCounts.put(transitionName, number);
-    }
-
-    return choiceDistributionCounts;
+    return environment.get(DbSession.class).findChoiceDistribution(processDefinitionId, activityName);
   }
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,18 +21,33 @@
  */
 package org.jbpm.pvm.internal.query;
 
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
 import org.jbpm.api.Deployment;
 import org.jbpm.api.DeploymentQuery;
 import org.jbpm.api.QueryOperator;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.repository.DeploymentImpl;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query deployment.
+ *
+ *   select
+ *     deployment
+ *     count
+ *   where
+ *     dbid(deploymentId)
+ *     state(suspended)
+ *   order by
+ *     timestamp
+ *     state
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class DeploymentQueryImpl extends AbstractQuery implements DeploymentQuery {
 
@@ -41,45 +56,8 @@
   protected Long[] deploymentId;
   protected Boolean suspended;
 
-  protected String hql() {
-    StringBuilder hql = new StringBuilder();
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-    hql.append("select ");
-    if (count) {
-      hql.append("count(d) ");
-    }
-    else {
-      hql.append("d ");
-    }
-
-    hql.append("from ");
-    hql.append(DeploymentImpl.class.getName());
-    hql.append(" as d ");
-
-    if (deploymentId != null) {
-      appendWhereClauseWithOperator("d.dbid", "deploymentId", hql);
-    }
-
-    if (suspended != null) {
-      if (suspended) {
-        appendWhereClause(" d.state = '" + Deployment.STATE_SUSPENDED + "' ", hql);
-      }
-      else {
-        appendWhereClause(" d.state != '" + Deployment.STATE_SUSPENDED + "' ", hql);
-      }
-    }
-
-    appendOrderByClause(hql);
-
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (deploymentId != null) {
-      applyParameterWithOperator("deploymentId", deploymentId, query);
-    }
-  }
-
   public DeploymentQuery deploymentId(String deploymentId) {
     this.deploymentId = new Long[] { Long.valueOf(deploymentId) };
     return this;
@@ -96,12 +74,12 @@
   }
 
   public DeploymentQuery orderAsc(String property) {
-    addOrderByClause("d." + property + " asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public DeploymentQuery orderDesc(String property) {
-    addOrderByClause("d." + property + " desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -126,4 +104,54 @@
     parameterOperators.put("deploymentId", operator);
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(DeploymentImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (deploymentId != null) {
+      QueryOperator operator = parameterOperators.get("deploymentId");
+      if (operator == null) {
+        queryProperty.addCondition("dbid", deploymentId[0], QueryOperator.EQUALS);
+      } else {
+        queryProperty.addCondition("dbid", deploymentId, operator);
+      }
+    }
+
+    if (suspended != null) {
+        if (suspended.equals(Boolean.TRUE)) {
+          queryProperty.addCondition("state", Deployment.STATE_SUSPENDED, QueryOperator.EQUALS);
+        } else {
+          queryProperty.addCondition("state", Deployment.STATE_SUSPENDED, QueryOperator.NOT_EQUALS);
+        }
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryActivityInstanceQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryActivityInstanceQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryActivityInstanceQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -22,25 +22,41 @@
 package org.jbpm.pvm.internal.query;
 
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
 import org.jbpm.api.JbpmException;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.history.HistoryActivityInstance;
 import org.jbpm.api.history.HistoryActivityInstanceQuery;
 import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 
 /**
+ * query history activity instance.
+ *
+ *   select
+ *     DeploymentImpl
+ *     count
+ *   where
+ *     id
+ *     key
+ *     name
+ *     state(suspended)
+ *     deploymentId
+ *   order by
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class HistoryActivityInstanceQueryImpl extends AbstractQuery implements HistoryActivityInstanceQuery {
 
   private static final long serialVersionUID = 1L;
-  
+
   protected String[] processDefinitionId;
   protected Long tookLessThen;
   protected Long tookLongerThen;
@@ -51,99 +67,12 @@
   protected String[] activityName;
   protected boolean completedOnly;
 
-  protected String hql() {
-  	StringBuilder hql = new StringBuilder();
-  	
-  	hql.append("select ");
-  	if (count) {
-  	  hql.append("count(hai) ");
-  	} else {
-  	  hql.append("hai ");
-  	}
-  	
-    hql.append("from ");
-    hql.append(HistoryActivityInstanceImpl.class.getName());
-    hql.append(" as hai ");
-    
-    if (processDefinitionId!=null) {
-      appendWhereClauseWithOperator("hai.historyProcessInstance.processDefinitionId", "processDefinitionId", hql);
-    }
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-    if (tookLessThen!=null) {
-      appendWhereClause(" hai.duration < :tookLessThen ", hql);
-    }
-    
-    if (tookLongerThen!=null) {
-      appendWhereClause(" hai.duration > :tookLongerThen ", hql);
-    }
-    
-    if (startedBefore!=null) {
-      appendWhereClause(" hai.startTime < :startedBefore ", hql);
-    }
-    
-    if (startedAfter!=null) {
-      appendWhereClause(" hai.startTime > :startedAfter ", hql);
-    }
-    
-    if (processInstanceId!=null) {
-      appendWhereClauseWithOperator("hai.historyProcessInstance.processInstanceId", "processInstanceId", hql);
-    }
-    
-    if (executionId!=null) {
-      appendWhereClauseWithOperator("hai.executionId", "executionId", hql);
-    }
-    
-    if (activityName!=null) {
-      appendWhereClauseWithOperator("hai.activityName", "activityName", hql);
-    }
-    
-    if (completedOnly) {
-      appendWhereClause(" hai.endTime is not null ", hql);
-    }
-    
-    appendOrderByClause(hql);
-
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (tookLessThen!=null) {
-      query.setLong("tookLessThen", tookLessThen);
-    }
-    
-    if (tookLongerThen!=null) {
-      query.setLong("tookLongerThen", tookLongerThen);
-    }
-    
-    if (startedBefore!=null) {
-      query.setTimestamp("startedBefore", startedBefore);
-    }
-    
-    if (startedAfter!=null) {
-      query.setTimestamp("startedAfter", startedAfter);
-    }
-    
-    if (processDefinitionId!=null) {
-      applyParameterWithOperator("processDefinitionId", processDefinitionId, query);
-    }
-    
-    if (processInstanceId!=null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-    
-    if (executionId!=null) {
-      applyParameterWithOperator("executionId", executionId, query);
-    }
-    
-    if (activityName!=null) {
-      applyParameterWithOperator("activityName", activityName, query);
-    }
-  }
-
   public List<HistoryActivityInstance> list() {
     return CollectionUtil.checkList(untypedList(), HistoryActivityInstance.class);
   }
-  
+
   public HistoryActivityInstance uniqueResult() {
     return (HistoryActivityInstance)untypedUniqueResult();
   }
@@ -157,19 +86,19 @@
     this.executionId = new String[] { executionId };
     return this;
   }
-  
+
   public HistoryActivityInstanceQuery processInstanceId(String processInstanceId) {
     this.processInstanceId = new String[] { processInstanceId };
     return this;
   }
 
   public HistoryActivityInstanceQuery orderAsc(String property) {
-    addOrderByClause("hai."+property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public HistoryActivityInstanceQuery orderDesc(String property) {
-    addOrderByClause("hai."+property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -205,7 +134,7 @@
     this.tookLongerThen = durationInMillis;
     return this;
   }
-  
+
   public HistoryActivityInstanceQuery completedOnly() {
     this.completedOnly = true;
     return this;
@@ -214,28 +143,98 @@
   public HistoryActivityInstanceQuery activityName(QueryOperator operator, String... activityName) {
     this.activityName = activityName;
     parameterOperators.put("activityName", operator);
-    
+
     return this;
   }
 
   public HistoryActivityInstanceQuery executionId(QueryOperator operator, String... executionId) {
     this.executionId = executionId;
     parameterOperators.put("executionId", operator);
-    
+
     return this;
   }
 
   public HistoryActivityInstanceQuery processDefinitionId(QueryOperator operator, String... processDefinitionId) {
     this.processDefinitionId = processDefinitionId;
     parameterOperators.put("processDefinitionId", operator);
-    
+
     return this;
   }
 
   public HistoryActivityInstanceQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(HistoryActivityInstanceImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (processDefinitionId != null) {
+      queryProperty.addCondition("historyProcessInstance.processDefinitionId", processDefinitionId, findOperator("processDefinitionId"));
+    }
+
+    if (tookLessThen != null) {
+      queryProperty.addCondition("tookLessThen", tookLessThen, QueryOperator.LESS_THAN);
+    }
+
+    if (tookLongerThen != null) {
+      queryProperty.addCondition("tookLongerThen", tookLongerThen, QueryOperator.GREATER_THAN);
+    }
+
+    if (startedBefore != null) {
+      queryProperty.addCondition("startedBefore", startedBefore, QueryOperator.LESS_THAN);
+    }
+
+    if (startedAfter != null) {
+      queryProperty.addCondition("startedAfter", startedAfter, QueryOperator.GREATER_THAN);
+    }
+
+    if (processInstanceId != null) {
+      queryProperty.addCondition("historyProcessInstance.processInstanceId", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (executionId != null) {
+      queryProperty.addCondition("executionId", executionId, findOperator("executionId"));
+    }
+
+    if (activityName != null) {
+      queryProperty.addCondition("activityName", activityName, findOperator("activityName"));
+    }
+
+    if (completedOnly) {
+      queryProperty.addCondition("endTime", null, QueryOperator.NOT_NULL);
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryDetailQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryDetailQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryDetailQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -22,97 +22,55 @@
 package org.jbpm.pvm.internal.query;
 
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
-
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.history.HistoryDetail;
 import org.jbpm.api.history.HistoryDetailQuery;
 import org.jbpm.pvm.internal.history.model.HistoryCommentImpl;
 import org.jbpm.pvm.internal.history.model.HistoryDetailImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query history activity instance.
+ *
+ *   select
+ *     HistoryDetailImpl
+ *     count
+ *   where
+ *     timeBefore
+ *     timeAfter
+ *     processInstanceId
+ *     activityInstanceId
+ *     taskId
+ *   order by
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class HistoryDetailQueryImpl extends AbstractQuery implements HistoryDetailQuery {
 
+  private static final long serialVersionUID = 1L;
+
   protected Class<?> type = HistoryDetailImpl.class;
 
   protected Date timeBefore;
   protected Date timeAfter;
-  
+
   protected String[] processInstanceId;
   protected String[] activityInstanceId;
   protected String[] taskId;
 
-  private static final long serialVersionUID = 1L;
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-  protected String hql() {
-    StringBuilder hql = new StringBuilder();
-    hql.append("select ");
-    if (count) {
-      hql.append("count(hd) ");      
-    } else {
-      hql.append("hd ");
-    }
-    hql.append("from ");
-    hql.append(type.getName());
-    hql.append(" as hd ");
-    
-    if (taskId!=null) {
-      appendWhereClauseWithOperator("hd.historyTask.dbid", "taskId", hql);
-    }
-    
-    if (processInstanceId!=null) {
-      appendWhereClauseWithOperator("hd.historyProcessInstance.processInstanceId", "processInstanceId", hql);
-    }
-    
-    if (activityInstanceId!=null) {
-      appendWhereClauseWithOperator("hd.historyActivityInstance.dbid", "activityInstanceId", hql);
-    }
-    
-    if (timeBefore!=null) {
-      appendWhereClause(" hd.time < :timeBefore ", hql);
-    }
-    
-    if (timeAfter!=null) {
-      appendWhereClause(" hd.time > :timeAfter ", hql);
-    }
-    
-    appendOrderByClause(hql);
-    
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (timeAfter!=null) {
-      query.setTime("timeAfter", timeAfter);
-    }
-    
-    if (timeBefore!=null) {
-      query.setTime("timeBefore", timeBefore);
-    }
-    
-    if (taskId!=null) {
-      applyParameterWithOperator("taskId", taskId, query);
-    }
-    
-    if (processInstanceId!=null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-    
-    if (activityInstanceId!=null) {
-      applyParameterWithOperator("activityInstanceId", activityInstanceId, query);
-    }
-  }
-
   public List<HistoryDetail> list() {
     return CollectionUtil.checkList(untypedList(), HistoryDetail.class);
   }
-  
+
   public HistoryDetail uniqueResult() {
     return (HistoryDetail) untypedUniqueResult();
   }
@@ -124,11 +82,13 @@
 
   public HistoryDetailQuery orderAsc(String property) {
     addOrderByClause("hd."+property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public HistoryDetailQuery orderDesc(String property) {
     addOrderByClause("hd."+property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -165,21 +125,75 @@
   public HistoryDetailQuery activityInstanceId(QueryOperator operator, String... activityInstanceId) {
     this.activityInstanceId = activityInstanceId;
     parameterOperators.put("activityInstanceId", operator);
-    
+
     return this;
   }
 
   public HistoryDetailQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
 
   public HistoryDetailQuery taskId(QueryOperator operator, String... taskId) {
     this.taskId = taskId;
     parameterOperators.put("taskId", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(type.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (taskId != null) {
+      queryProperty.addCondition("historyTask.dbid", taskId, findOperator("taskId"));
+    }
+
+    if (processInstanceId != null) {
+      queryProperty.addCondition("historyProcessInstance.processInstanceId", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (activityInstanceId != null) {
+      queryProperty.addCondition("historyActivityInstance.dbid", activityInstanceId, findOperator("activityInstanceId"));
+    }
+
+    if (timeBefore != null) {
+      queryProperty.addCondition("timeBefore", timeBefore, QueryOperator.LESS_THAN);
+    }
+
+    if (timeAfter != null) {
+      queryProperty.addCondition("timeAfter", timeAfter, QueryOperator.GREATER_THAN);
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryProcessInstanceQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryProcessInstanceQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryProcessInstanceQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -22,24 +22,44 @@
 package org.jbpm.pvm.internal.query;
 
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.history.HistoryProcessInstance;
 import org.jbpm.api.history.HistoryProcessInstanceQuery;
 import org.jbpm.pvm.internal.history.model.HistoryProcessInstanceImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query history process instance.
+ *
+ *   select
+ *     HistoryProcessInstanceImpl
+ *     count
+ *   where
+ *     processDefinitionId
+ *     state
+ *     processInstanceId
+ *     processInstanceKey
+ *     initiator
+ *     superProcessInstanceId
+ *     ended
+ *     endedBefore
+ *     endedAfter
+ *   order by
+ *
  * @author Tom Baeyens
  * @author Alejandro Guizar
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class HistoryProcessInstanceQueryImpl extends AbstractQuery implements HistoryProcessInstanceQuery {
 
   private static final long serialVersionUID = 1L;
-  
+
   protected String[] processDefinitionId;
   protected String[] state;
   protected String[] processInstanceId;
@@ -50,98 +70,13 @@
   protected boolean ended;
   protected Date endedBefore;
   protected Date endedAfter;
-  
 
-  protected String hql() {
-  	StringBuilder hql = new StringBuilder();
-  	
-  	hql.append("select ");
-  	if (count) {
-  	  hql.append("count(hpi) ");
-  	} else {
-  	  hql.append("hpi ");
-  	}
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-    hql.append("from ");
-    hql.append(HistoryProcessInstanceImpl.class.getName());
-    hql.append(" as hpi ");
-    
-    if (processInstanceId!=null) {
-      appendWhereClauseWithOperator("hpi.processInstanceId", "processInstanceId", hql);
-    }
-    
-    if (processDefinitionId!=null) {
-      appendWhereClauseWithOperator("hpi.processDefinitionId", "processDefinitionId", hql);
-    }
-    
-    if (state!=null) {
-      appendWhereClauseWithOperator("hpi.state", "state", hql);
-    }
-    
-    if (processInstanceKey!=null) {
-      appendWhereClauseWithOperator("hpi.key", "processInstanceKey", hql);
-    }
-    
-    if (initiator!=null) {
-      appendWhereClauseWithOperator("hpi.initiator", "initiator", hql);
-    }
-    
-    if (superProcessInstanceId!=null) {
-      appendWhereClauseWithOperator("hpi.superProcessInstanceId", "superProcessInstanceId", hql);
-    }
-    
-    if (ended) {
-      appendWhereClause(" hpi.endTime is not null", hql);
-    }
-    if (endedBefore != null) {
-      appendWhereClause(" hpi.endTime < :before", hql);
-    }
-    if (endedAfter != null) {
-      appendWhereClause(" hpi.endTime >= :after", hql);
-    }
-
-    appendOrderByClause(hql);
-    
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (endedBefore != null) {
-      query.setTimestamp("before", endedBefore);
-    }
-    if (endedAfter != null) {
-      query.setTimestamp("after", endedAfter);
-    }
-    
-    if (processInstanceId!=null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-    
-    if (processDefinitionId!=null) {
-      applyParameterWithOperator("processDefinitionId", processDefinitionId, query);
-    }
-    
-    if (state!=null) {
-      applyParameterWithOperator("state", state, query);
-    }
-    
-    if (processInstanceKey!=null) {
-      applyParameterWithOperator("processInstanceKey", processInstanceKey, query);
-    }
-    
-    if (initiator!=null) {
-      applyParameterWithOperator("initiator", initiator, query);
-    }
-    
-    if (superProcessInstanceId!=null) {
-      applyParameterWithOperator("superProcessInstanceId", superProcessInstanceId, query);
-    }
-  }
-
   public List<HistoryProcessInstance> list() {
     return CollectionUtil.checkList(untypedList(), HistoryProcessInstance.class);
   }
-  
+
   public HistoryProcessInstance uniqueResult() {
     return (HistoryProcessInstance)untypedUniqueResult();
   }
@@ -153,11 +88,13 @@
 
   public HistoryProcessInstanceQuery orderAsc(String property) {
     addOrderByClause("hpi."+property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public HistoryProcessInstanceQuery orderDesc(String property) {
     addOrderByClause("hpi."+property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -170,7 +107,7 @@
     this.processDefinitionId = new String[] { processDefinitionId };
     return this;
   }
-  
+
   public HistoryProcessInstanceQuery processInstanceKey(String processInstanceKey) {
     this.processInstanceKey = new String[] { processInstanceKey };
     return this;
@@ -180,7 +117,7 @@
     this.state = new String[] { state };
     return this;
   }
-  
+
   public HistoryProcessInstanceQuery initiator(String user) {
     this.initiator = new String[] { user };
     return this;
@@ -213,48 +150,117 @@
   public HistoryProcessInstanceQuery processDefinitionId(QueryOperator operator, String... processDefinitionId) {
     this.processDefinitionId = processDefinitionId;
     parameterOperators.put("processDefinitionId", operator);
-    
+
     return this;
   }
 
   public HistoryProcessInstanceQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
 
   public HistoryProcessInstanceQuery processInstanceKey(QueryOperator operator, String... processInstanceKey) {
     this.processInstanceKey = processInstanceKey;
     parameterOperators.put("processInstanceKey", operator);
-    
+
     return this;
   }
 
   public HistoryProcessInstanceQuery state(QueryOperator operator, String... state) {
     this.state = state;
     parameterOperators.put("state", operator);
-    
+
     return this;
   }
-  
+
   public HistoryProcessInstanceQuery initiator(QueryOperator operator, String... userId) {
     this.initiator = userId;
     parameterOperators.put("initiator", operator);
-    
+
     return this;
   }
 
   public HistoryProcessInstanceQuery superProcessInstanceId(String processInstanceId) {
     this.superProcessInstanceId = new String[] { processInstanceId };
-    
+
     return this;
   }
 
   public HistoryProcessInstanceQuery superProcessInstanceId(QueryOperator operator, String... processInstanceId) {
     this.superProcessInstanceId = processInstanceId;
     parameterOperators.put("superProcessInstanceId", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+    // key
+    queryProperty.setKey(HistoryProcessInstanceImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (processInstanceId != null) {
+      queryProperty.addCondition("processInstanceId", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (processDefinitionId != null) {
+      queryProperty.addCondition("processDefinitionId", processDefinitionId, findOperator("processDefinitionId"));
+    }
+
+    if (state != null) {
+      queryProperty.addCondition("state", state, findOperator("state"));
+    }
+
+    if (processInstanceKey != null) {
+      queryProperty.addCondition("key", processInstanceKey, findOperator("processInstanceKey"));
+    }
+
+    if (initiator != null) {
+      queryProperty.addCondition("initiator", initiator, findOperator("initiator"));
+    }
+
+    if (superProcessInstanceId != null) {
+      queryProperty.addCondition("superProcessInstanceId", superProcessInstanceId, findOperator("superProcessInstanceId"));
+    }
+
+    if (ended) {
+      queryProperty.addCondition("endTime", null, QueryOperator.NOT_NULL);
+    }
+
+    if (endedBefore != null) {
+      queryProperty.addCondition("endedBefore", endedBefore, QueryOperator.LESS_THAN);
+    }
+
+    if (endedAfter != null) {
+      queryProperty.addCondition("endedAfter", endedAfter, QueryOperator.GREATER_THAN);
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -22,23 +22,44 @@
 package org.jbpm.pvm.internal.query;
 
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
-
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.history.HistoryTask;
 import org.jbpm.api.history.HistoryTaskQuery;
 import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
-import org.jbpm.pvm.internal.history.model.HistoryTaskInstanceImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query history task.
+ *
+ *   select
+ *     HistoryTaskImpl
+ *     count
+ *   where
+ *     taskId
+ *     executionId
+ *     processInstanceId
+ *     assignee
+ *     state
+ *     outcome
+ *     tookLessThen
+ *     tookLongerThen
+ *     startedBefore
+ *     startedAfter
+ *   order by
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class HistoryTaskQueryImpl extends AbstractQuery implements HistoryTaskQuery {
 
+  private static final long serialVersionUID = 1L;
+
   protected Long[] taskId;
   protected String[] executionId;
   protected String[] processInstanceId;
@@ -50,117 +71,12 @@
   protected Date startedBefore;
   protected Date startedAfter;
 
-  private static final long serialVersionUID = 1L;
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-  protected String hql() {
-    StringBuilder hql = new StringBuilder();
-    
-    hql.append("select ");
-    if (count) {
-      hql.append("count(ht) ");
-    } else {
-      hql.append("ht ");
-    }
-    
-    hql.append("from ");
-    hql.append(HistoryTaskImpl.class.getName());
-    hql.append(" as ht ");
-    
-    if (processInstanceId != null) {
-      hql.append(", ");
-      hql.append(HistoryTaskInstanceImpl.class.getName());
-      hql.append(" as hti ");
-      appendWhereClause("ht = hti.historyTask", hql);
-      appendWhereClauseWithOperator("hti.historyProcessInstance.processInstanceId", "processInstanceId", hql);
-    }
-    
-    if (taskId!=null) {
-      appendWhereClauseWithOperator("ht.dbid", "taskId", hql);
-    }
-    
-    if (executionId!=null) {
-      appendWhereClauseWithOperator("ht.executionId", "executionId", hql);
-    }
-    
-    if (assignee!=null) {
-      appendWhereClauseWithOperator("ht.assignee", "assignee", hql);
-    }
-
-    if (state!=null) {
-      appendWhereClauseWithOperator("ht.state", "state", hql);
-    }
-
-    if (outcome!=null) {
-      appendWhereClauseWithOperator("ht.outcome", "outcome", hql);
-    }
-
-    if (tookLessThen!=null) {
-      appendWhereClause(" ht.duration < :tookLessThen ", hql);
-    }
-    
-    if (tookLongerThen!=null) {
-      appendWhereClause(" ht.duration > :tookLongerThen ", hql);
-    }
-
-    if (startedBefore!=null) {
-      appendWhereClause(" ht.createTime < :startedBefore ", hql);
-    }
-    
-    if (startedAfter!=null) {
-      appendWhereClause(" ht.createTime > :startedAfter ", hql);
-    }
-    
-    appendOrderByClause(hql);
-    
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (tookLessThen!=null) {
-      query.setLong("tookLessThen", tookLessThen);
-    }
-    
-    if (tookLongerThen!=null) {
-      query.setLong("tookLongerThen", tookLongerThen);
-    }
-    
-    if (startedBefore!=null) {
-      query.setTimestamp("startedBefore", startedBefore);
-    }
-    
-    if (startedAfter!=null) {
-      query.setTimestamp("startedAfter", startedAfter);
-    }
-    
-    if (processInstanceId!=null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-    
-    if (taskId!=null) {
-      applyParameterWithOperator("taskId", taskId, query);
-    }
-    
-    if (executionId!=null) {
-      applyParameterWithOperator("executionId", executionId, query);
-    }
-    
-    if (assignee!=null) {
-      applyParameterWithOperator("assignee", assignee, query);
-    }
-
-    if (state!=null) {
-      applyParameterWithOperator("state", state, query);
-    }
-
-    if (outcome!=null) {
-      applyParameterWithOperator("outcome", outcome, query);
-    }
-  }
-
   public List<HistoryTask> list() {
     return CollectionUtil.checkList(untypedList(), HistoryTask.class);
   }
-  
+
   public HistoryTask uniqueResult() {
     return (HistoryTask) untypedUniqueResult();
   }
@@ -174,7 +90,7 @@
     this.processInstanceId = new String[] { processInstanceId };
     return this;
   }
-  
+
   public HistoryTaskQuery executionId(String executionId) {
     this.executionId = new String[] { executionId };
     return this;
@@ -197,11 +113,13 @@
 
   public HistoryTaskQuery orderAsc(String property) {
     addOrderByClause("ht."+property+" asc");
+    orders.put("ht." + property, "asc");
     return this;
   }
 
   public HistoryTaskQuery orderDesc(String property) {
     addOrderByClause("ht."+property+" desc");
+    orders.put("ht." + property, "desc");
     return this;
   }
 
@@ -233,28 +151,28 @@
   public HistoryTaskQuery assignee(QueryOperator operator, String... assignee) {
     this.assignee = assignee;
     parameterOperators.put("assignee", operator);
-    
+
     return this;
   }
-  
+
   public HistoryTaskQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
 
   public HistoryTaskQuery executionId(QueryOperator operator, String... executionId) {
     this.executionId = executionId;
     parameterOperators.put("executionId", operator);
-    
+
     return this;
   }
 
   public HistoryTaskQuery state(QueryOperator operator, String... state) {
     this.state = state;
     parameterOperators.put("state", operator);
-    
+
     return this;
   }
 
@@ -264,14 +182,88 @@
       this.taskId[i] = Long.valueOf(taskId[i]);
     }
     parameterOperators.put("taskId", operator);
-    
+
     return this;
   }
-  
+
   public HistoryTaskQuery outcome(QueryOperator operator, String... outcome) {
     this.outcome = outcome;
     parameterOperators.put("outcome", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(HistoryTaskImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (processInstanceId != null) {
+      queryProperty.addCondition("processInstanceId", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (taskId != null) {
+      queryProperty.addCondition("ht.dbid", taskId, findOperator("taskId"));
+    }
+
+    if (assignee != null) {
+      queryProperty.addCondition("ht.assignee", assignee, findOperator("assignee"));
+    }
+
+    if (executionId != null) {
+      queryProperty.addCondition("ht.executionId", executionId, findOperator("executionId"));
+    }
+
+    if (state != null) {
+      queryProperty.addCondition("ht.state", state, findOperator("state"));
+    }
+
+    if (outcome != null) {
+      queryProperty.addCondition("ht.outcome", outcome, findOperator("outcome"));
+    }
+
+    if (tookLessThen != null) {
+      queryProperty.addCondition("tookLessThen", tookLessThen, QueryOperator.LESS_THAN);
+    }
+
+    if (tookLongerThen != null) {
+      queryProperty.addCondition("tookLongerThen", tookLongerThen, QueryOperator.GREATER_THAN);
+    }
+
+    if (startedBefore != null) {
+      queryProperty.addCondition("startedBefore", startedBefore, QueryOperator.LESS_THAN);
+    }
+
+    if (startedAfter != null) {
+      queryProperty.addCondition("startedAfter", startedAfter, QueryOperator.GREATER_THAN);
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,78 +21,50 @@
  */
 package org.jbpm.pvm.internal.query;
 
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
-
 import org.jbpm.api.JobQuery;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.job.Job;
 import org.jbpm.pvm.internal.job.JobImpl;
 import org.jbpm.pvm.internal.job.MessageImpl;
 import org.jbpm.pvm.internal.job.TimerImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query job.
+ *
+ *   select
+ *     JobImpl,MessageImpl,TimerImpl(messagesOnly,timersOnly)
+ *     count
+ *   where
+ *     processInstanceId
+ *     exception
+ *   order by
+ *     ?
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class JobQueryImpl extends AbstractQuery implements JobQuery {
-  
+
   private static final long serialVersionUID = 1L;
 
-  protected boolean messagesOnly; 
+  protected boolean messagesOnly;
   protected boolean timersOnly;
   protected String[] processInstanceId;
   protected Boolean exception;
 
-  protected String hql() {
-  	StringBuilder hql = new StringBuilder();
-  	
-  	hql.append("select ");
-  	if (count) {
-  	  hql.append("count(j) ");
-  	} else {
-  	  hql.append("j ");
-  	}
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-    hql.append("from ");
-    if (messagesOnly) {
-      hql.append(MessageImpl.class.getName());
-    } else if (timersOnly) {
-      hql.append(TimerImpl.class.getName());
-    } else {
-      hql.append(JobImpl.class.getName());
-    }
-    hql.append(" j ");
-
-    if (processInstanceId!=null) {
-      appendWhereClauseWithOperator("j.processInstance.id", "processInstanceId", hql);
-    } 
-
-    if (exception!=null) {
-      if (exception) {
-        appendWhereClause("j.exception is not null ", hql);
-      } else {
-        appendWhereClause("j.exception is null ", hql);
-      }
-    }
-    
-    appendOrderByClause(hql);
-
-    return hql.toString();
-  }
-
-  protected void applyParameters(Query query) {
-    if (processInstanceId != null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-  }
-
   public List<Job> list() {
     return CollectionUtil.checkList(untypedList(), Job.class);
   }
-  
+
   public Job uniqueResult() {
     return (Job)untypedUniqueResult();
   }
@@ -113,12 +85,12 @@
   }
 
   public JobQuery orderAsc(String property) {
-    addOrderByClause("j."+property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public JobQuery orderDesc(String property) {
-    addOrderByClause("j."+property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -131,11 +103,56 @@
     this.processInstanceId = new String[] { processInstanceId };
     return this;
   }
-  
+
   public JobQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    if (messagesOnly) {
+      queryProperty.setKey(MessageImpl.class.getName());
+    } else if (timersOnly) {
+      queryProperty.setKey(TimerImpl.class.getName());
+    } else {
+      queryProperty.setKey(JobImpl.class.getName());
+    }
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    } else if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+    }
+
+    // conditions
+    if (processInstanceId != null) {
+      queryProperty.addCondition("processInstance.id", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (exception != null) {
+      if (exception) {
+        queryProperty.addCondition("exception", null, QueryOperator.NOT_NULL);
+      } else {
+        queryProperty.addCondition("exception", null, QueryOperator.IS_NULL);
+      }
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,41 +21,48 @@
  */
 package org.jbpm.pvm.internal.query;
 
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.hibernate.Query;
-import org.hibernate.Session;
 import org.jbpm.api.Deployment;
 import org.jbpm.api.ProcessDefinition;
 import org.jbpm.api.ProcessDefinitionQuery;
 import org.jbpm.api.QueryOperator;
-import org.jbpm.pvm.internal.env.EnvironmentImpl;
 import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
-import org.jbpm.pvm.internal.repository.DeploymentImpl;
-import org.jbpm.pvm.internal.repository.DeploymentProperty;
-import org.jbpm.pvm.internal.session.RepositorySession;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 
-/** returns partially initialized ProcessDefinitionImpl's that can only be exposed 
+/** returns partially initialized ProcessDefinitionImpl's that can only be exposed
  * as {@link ProcessDefinition}.
- * 
+ *
  * To get the properly initialized {@link ProcessDefinitionImpl} objects,
- * use {@link RepositorySession#findProcessDefinitionById(String)} or 
+ * use {@link RepositorySession#findProcessDefinitionById(String)} or
  * {@link RepositorySession#findProcessDefinitionByKey(String)}
- * 
- * You can use the query query capabilities in this class to find the id 
+ *
+ * You can use the query query capabilities in this class to find the id
  * and then use  {@link RepositorySession#findProcessDefinitionById(String)}
  * to get the properly initialized ProcessDefinitionImpl.
- * 
+ *
+ *   select
+ *     DeploymentImpl
+ *     count
+ *   where
+ *     id
+ *     key
+ *     name
+ *     state(suspended)
+ *     deploymentId
+ *   order by
+ *     ?
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class ProcessDefinitionQueryImpl extends AbstractQuery implements ProcessDefinitionQuery {
-  
+
   private static final long serialVersionUID = 1L;
 
   protected String[] id;
@@ -63,116 +70,17 @@
   protected String[] name;
   protected Boolean suspended;
   protected Long[] deploymentId;
-  
-  public Object execute(Session session) {
-    Object result = super.execute(session);
-    RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class);
 
-    if (uniqueResult) {
-      if (result == null) return null;
-      return getProcessDefinition(repositorySession, result);
-    }
-    else {
-      List<?> propertyMaps = (List<?>) result;
-      if (propertyMaps.isEmpty()) return Collections.EMPTY_LIST;
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
 
-      List<ProcessDefinition> processDefinitions = new ArrayList<ProcessDefinition>();
-      for (Object propertyObject: propertyMaps) {
-        ProcessDefinitionImpl processDefinition = getProcessDefinition(repositorySession, propertyObject);
-        processDefinitions.add(processDefinition);
-      }
-      return processDefinitions;
-    }
-  }
-
-  private static ProcessDefinitionImpl getProcessDefinition(RepositorySession repositorySession,
-    Object propertyObject) {
-    Map<?, ?> propertyMap = (Map<?, ?>) propertyObject;
-    String deploymentId = propertyMap.get("deploymentDbid").toString();
-    String objectName = (String)propertyMap.get("objectName");
-    return (ProcessDefinitionImpl) repositorySession.getObject(deploymentId, objectName);
-  }
-
-  protected String hql() {
-  	StringBuilder hql = new StringBuilder();
-    hql.append("select new map( idProperty.objectName as objectName, " +
-    		                   "idProperty.deployment.dbid as deploymentDbid ) ");
-    hql.append("from ");
-    hql.append(DeploymentImpl.class.getName());
-    hql.append(" as deployment, ");
-    hql.append(DeploymentProperty.class.getName());
-    hql.append(" as idProperty, ");
-    hql.append(DeploymentProperty.class.getName());
-    hql.append(" as keyProperty, ");
-    hql.append(DeploymentProperty.class.getName());
-    hql.append(" as versionProperty ");
-
-    if (suspended!=null) {
-      if (suspended) {
-        appendWhereClause("deployment.state = '"+Deployment.STATE_SUSPENDED+"'", hql);
-      } else {
-        appendWhereClause("deployment.state != '"+Deployment.STATE_SUSPENDED+"'", hql);
-      }
-    }
-
-    appendWhereClause("idProperty.key = '"+DeploymentImpl.KEY_PROCESS_DEFINITION_ID+"'", hql);
-    appendWhereClause("idProperty.deployment = deployment ", hql);
-
-    appendWhereClause("keyProperty.key = '"+DeploymentImpl.KEY_PROCESS_DEFINITION_KEY+"' ", hql);
-    appendWhereClause("keyProperty.objectName = idProperty.objectName ", hql);
-    appendWhereClause("keyProperty.deployment = deployment ", hql);
-
-    appendWhereClause("versionProperty.key = '"+DeploymentImpl.KEY_PROCESS_DEFINITION_VERSION+"' ", hql);
-    appendWhereClause("versionProperty.objectName = idProperty.objectName ", hql);
-    appendWhereClause("versionProperty.deployment = deployment ", hql);
-
-    if (id!=null) {
-      appendWhereClauseWithOperator("idProperty.stringValue", "id", hql);
-    }
-
-    if (name!=null) {
-      appendWhereClauseWithOperator("idProperty.objectName", "name", hql);
-    }
-
-    if (key!=null) {
-      appendWhereClauseWithOperator("keyProperty.stringValue", "key", hql);
-    }
-    
-    if (deploymentId!=null) {
-      appendWhereClauseWithOperator("idProperty.deployment.dbid", "deploymentId", hql);
-    }
-    
-    appendOrderByClause(hql);
-
-    return hql.toString();
-  }
-  
-  protected void applyParameters(Query query) {
-    if (id != null) {
-      applyParameterWithOperator("id", id, query);
-    }
-    
-    if (name != null) {
-      applyParameterWithOperator("name", name, query);
-    }
-    
-    if (key != null) {
-      applyParameterWithOperator("key", key, query);
-    }
-    
-    if (deploymentId != null) {
-      applyParameterWithOperator("deploymentId", deploymentId, query);
-    }
-  }
-  
   public List<ProcessDefinition> list() {
     return CollectionUtil.checkList(untypedList(), ProcessDefinition.class);
   }
-  
+
   public ProcessDefinition uniqueResult() {
     return (ProcessDefinition) untypedUniqueResult();
   }
-  
+
   @Override
   public long count() {
     return list().size(); // TODO: change this to a real db count, as with the other query types
@@ -187,7 +95,7 @@
     this.key = new String[] { key };
     return this;
   }
-  
+
   public ProcessDefinitionQuery suspended() {
     this.suspended = true;
     return this;
@@ -212,15 +120,17 @@
   public ProcessDefinitionQuery deploymentId(String deploymentId) {
     this.deploymentId = new Long[] { Long.valueOf(deploymentId) };
     return this;
-  } 
+  }
 
   public ProcessDefinitionQuery orderAsc(String property) {
-    addOrderByClause(property+" asc");
+    // addOrderByClause(property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public ProcessDefinitionQuery orderDesc(String property) {
-    addOrderByClause(property+" desc");
+    // addOrderByClause(property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -235,28 +145,86 @@
       this.deploymentId[i] = Long.valueOf(deploymentId[i]);
     }
     parameterOperators.put("deploymentId", operator);
-    
+
     return this;
   }
 
   public ProcessDefinitionQuery processDefinitionId(QueryOperator operator, String... processDefinitionId) {
     this.id = processDefinitionId;
     parameterOperators.put("processDefinitionId", operator);
-    
+
     return this;
   }
 
   public ProcessDefinitionQuery processDefinitionKey(QueryOperator operator, String... processDefinitionKey) {
     this.key = processDefinitionKey;
     parameterOperators.put("key", operator);
-    
+
     return this;
   }
 
   public ProcessDefinitionQuery processDefinitionName(QueryOperator operator, String... processDefinitionName) {
     this.name = processDefinitionName;
     parameterOperators.put("name", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(ProcessDefinitionImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (suspended != null) {
+        if (suspended.equals(Boolean.TRUE)) {
+          queryProperty.addCondition("deployment.state", Deployment.STATE_SUSPENDED, QueryOperator.EQUALS);
+        } else {
+          queryProperty.addCondition("deployment.state", Deployment.STATE_SUSPENDED, QueryOperator.NOT_EQUALS);
+        }
+    }
+
+    if (id != null) {
+      queryProperty.addCondition("idProperty.stringValue", id, findOperator("id"));
+    }
+
+    if (name != null) {
+      queryProperty.addCondition("idProperty.objectName", name, findOperator("name"));
+    }
+
+    if (key != null) {
+      queryProperty.addCondition("keyProperty.stringValue", key, findOperator("key"));
+    }
+
+    if (deploymentId != null) {
+      queryProperty.addCondition("idProperty.deployment.dbid", deploymentId, findOperator("deploymentId"));
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,21 +21,39 @@
  */
 package org.jbpm.pvm.internal.query;
 
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
 import org.jbpm.api.ProcessInstance;
 import org.jbpm.api.ProcessInstanceQuery;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.pvm.internal.model.ExecutionImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query process instance.
+ *
+ *   select
+ *     executionImpl
+ *     count
+ *   where
+ *     parent is null
+ *     processDefinitionId
+ *     id(processInstanceId)
+ *     key(processInstanceKey)
+ *     state(suspended)
+ *     initiator
+ *   order by
+ *     ?
+ *
  * @author Tom Baeyens
  * @author Maciej Swiderski
+ * @author Huisheng Xu
  */
 public class ProcessInstanceQueryImpl extends AbstractQuery implements ProcessInstanceQuery {
-  
+
   private static final long serialVersionUID = 1L;
 
   protected String[] processDefinitionId;
@@ -44,6 +62,8 @@
   protected Boolean suspended;
   protected String[] initiator;
 
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
+
   public ProcessInstance uniqueResult() {
     return (ProcessInstance)untypedUniqueResult();
   }
@@ -52,76 +72,13 @@
     return CollectionUtil.checkList(untypedList(), ProcessInstance.class);
   }
 
-  protected String hql() {
-  	StringBuilder hql = new StringBuilder();
-  	
-  	hql.append("select ");
-  	if (count) {
-  	  hql.append("count(processInstance) ");  	  
-  	} else {
-  	  hql.append("processInstance ");
-  	}
-  	
-    hql.append("from ");
-    hql.append(ExecutionImpl.class.getName());
-    hql.append(" as processInstance ");
-    
-    appendWhereClause("processInstance.parent is null ", hql);
-
-    if (suspended!=null) {
-      if (suspended) {
-        appendWhereClause("processInstance.state = '"+ExecutionImpl.STATE_SUSPENDED+"' ", hql);
-      } else {
-        appendWhereClause("processInstance.state != '"+ExecutionImpl.STATE_SUSPENDED+"' ", hql);
-      }
-    }
-
-    if (processInstanceId != null) {
-      appendWhereClauseWithOperator("processInstance.processInstance.id", "processInstanceId", hql);
-    }
-
-    if (processDefinitionId != null) {
-      appendWhereClauseWithOperator("processInstance.processDefinitionId", "processDefinitionId", hql);
-    }
-    
-    if (processInstanceKey != null) {
-      appendWhereClauseWithOperator("processInstance.key", "processInstanceKey", hql);
-    }
-    
-    if (initiator!=null) {
-      appendWhereClauseWithOperator("processInstance.initiator", "initiator", hql);
-    }
-
-    appendOrderByClause(hql);
-
-    return hql.toString();
-  }
-  
-  protected void applyParameters(Query query) {
-    if (processInstanceId != null) {
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-
-    if (processDefinitionId != null) {
-      applyParameterWithOperator("processDefinitionId", processDefinitionId, query);
-    }
-    
-    if (processInstanceKey != null) {
-      applyParameterWithOperator("processInstanceKey", processInstanceKey, query);
-    }
-    
-    if (initiator!=null) {
-      applyParameterWithOperator("initiator", initiator, query);
-    }
-  }
-
   public ProcessInstanceQuery orderAsc(String property) {
-    addOrderByClause("processInstance."+property+" asc");
+    orders.put(property, "asc");
     return this;
   }
 
   public ProcessInstanceQuery orderDesc(String property) {
-    addOrderByClause("processInstance."+property+" desc");
+    orders.put(property, "desc");
     return this;
   }
 
@@ -149,7 +106,7 @@
     this.processInstanceKey = new String[] { processInstanceKey };
     return this;
   }
-  
+
   public ProcessInstanceQuery initiator(String user) {
     this.initiator = new String[] { user };
     return this;
@@ -161,7 +118,7 @@
   }
   public String operator(String parameter, QueryOperator operator) {
     parameterOperators.put(parameter, operator);
-    
+
     return parameter;
   }
 
@@ -182,11 +139,71 @@
     parameterOperators.put("processInstanceKey", operator);
     return this;
   }
-  
+
   public ProcessInstanceQuery initiator(QueryOperator operator, String... userId) {
     this.initiator = userId;
     parameterOperators.put("initiator", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(ExecutionImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    queryProperty.addCondition("parent", null, QueryOperator.IS_NULL);
+
+    if (suspended != null) {
+        if (suspended.equals(Boolean.TRUE)) {
+          queryProperty.addCondition("state", ExecutionImpl.STATE_SUSPENDED, QueryOperator.EQUALS);
+        } else {
+          queryProperty.addCondition("state", ExecutionImpl.STATE_SUSPENDED, QueryOperator.NOT_EQUALS);
+        }
+    }
+
+    if (processInstanceId != null) {
+      queryProperty.addCondition("id", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (processDefinitionId != null) {
+      queryProperty.addCondition("processDefinitionId", processDefinitionId, findOperator("processDefinitionId"));
+    }
+
+    if (processInstanceKey != null) {
+      queryProperty.addCondition("key", processInstanceKey, findOperator("processInstanceKey"));
+    }
+
+    if (initiator != null) {
+      queryProperty.addCondition("initiator", initiator, findOperator("initiator"));
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryCondition.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryCondition.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryCondition.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.query;
+
+import org.jbpm.api.QueryOperator;
+
+/**
+ * query condition.
+ *
+ * @author Huisheng Xu
+ */
+public class QueryCondition {
+    private String name;
+
+    private Object value;
+
+    private QueryOperator operator;
+
+    public QueryCondition(String name, Object value, QueryOperator operator) {
+        this.name = name;
+        this.value = value;
+        this.operator = operator;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public QueryOperator getOperator() {
+        return operator;
+    }
+
+    @Override
+    public String toString() {
+        return "QueryCondition:{name:" + name + ",value:" + value + ",operator:" + operator + "}";
+    }
+}

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryProperty.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryProperty.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/QueryProperty.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.query;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.jbpm.api.QueryOperator;
+
+/**
+ * query property.
+ *
+ * @author Huisheng Xu
+ */
+public class QueryProperty {
+
+    public static final int RESULT_TYPE_LIST = 0;
+
+    public static final int RESULT_TYPE_COUNT = 1;
+
+    public static final int RESULT_TYPE_UNIQUE = 2;
+
+    public static final int RESULT_TYPE_PAGE = 3;
+
+    public static final int RESULT_TYPE_PAGE_COUNT = 4;
+
+    public static final int RESULT_TYPE_PAGE_UNIQUE = 5;
+
+    private int resultType = RESULT_TYPE_LIST;
+
+    private int firstResult;
+
+    private int maxResults;
+
+    private Map<String, QueryCondition> conditions = new LinkedHashMap<String, QueryCondition>();
+
+    private Map<String, String> orders = new LinkedHashMap<String, String>();
+
+    private String key;
+
+    public int getResultType() {
+        return resultType;
+    }
+
+    public void setResultType(int resultType) {
+        this.resultType = resultType;
+    }
+
+    // ~ ======================================================================
+    public int getFirstResult() {
+        return firstResult;
+    }
+
+    public void setFirstResult(int firstResult) {
+        this.firstResult = firstResult;
+    }
+
+    public int getMaxResults() {
+        return maxResults;
+    }
+
+    public void setMaxResults(int maxResults) {
+        this.maxResults = maxResults;
+    }
+
+    // ~ ======================================================================
+    public Map<String, QueryCondition> getConditions() {
+        return conditions;
+    }
+
+    public void addCondition(String name, Object value, QueryOperator operator) {
+        conditions.put(name, new QueryCondition(name, value, operator));
+    }
+
+    public boolean hasCondition(String name) {
+        return conditions.containsKey(name);
+    }
+
+    public QueryCondition getCondition(String name) {
+        return conditions.get(name);
+    }
+
+    public void removeCondition(String name) {
+        conditions.remove(name);
+    }
+
+    // ~ ======================================================================
+    public Map<String, String> getOrders() {
+        return orders;
+    }
+
+    public void addOrder(String order, String dir) {
+        orders.put(order, dir);
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+}

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -21,28 +21,36 @@
  */
 package org.jbpm.pvm.internal.query;
 
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.hibernate.Query;
-import org.hibernate.Session;
-
 import org.jbpm.api.JbpmException;
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.TaskQuery;
-import org.jbpm.api.identity.Group;
 import org.jbpm.api.task.Task;
 import org.jbpm.internal.log.Log;
-import org.jbpm.pvm.internal.env.EnvironmentImpl;
-import org.jbpm.pvm.internal.identity.spi.IdentitySession;
 import org.jbpm.pvm.internal.model.ExecutionImpl;
-import org.jbpm.pvm.internal.task.ParticipationImpl;
+import org.jbpm.pvm.internal.session.QuerySession;
 import org.jbpm.pvm.internal.task.TaskImpl;
 import org.jbpm.pvm.internal.util.CollectionUtil;
 
 /**
+ * query task.
+ *
+ *   select
+ *     taskImpl
+ *     count
+ *   where
+ *     assignee(assignee, unassigned)
+ *     participant(candidate)
+ *     executionId
+ *     processInstanceId
+ *     processDefinitionId
+ *     activityName
+ *   order by
+ *     ?
+ *
  * @author Tom Baeyens
  * @author Heiko Braun <heiko.braun at jboss.com>
  * @author Huisheng Xu
@@ -65,6 +73,8 @@
   /* groupIds transports the groupIds from the hql to the applyParameters */
   protected List<String> groupIds;
 
+  protected Map<String, String> orders = new LinkedHashMap<String, String>();
+
   public TaskQuery assignee(String assignee) {
     if (candidate != null) {
       throw new JbpmException("assignee(...) cannot be combined with candidate(...) in one query");
@@ -115,12 +125,12 @@
   }
 
   public TaskQuery orderAsc(String property) {
-    orderByClause = "task." + property + " asc ";
+    orders.put("task." + property, "asc");
     return this;
   }
 
   public TaskQuery orderDesc(String property) {
-    orderByClause = "task." + property + " desc ";
+    orders.put("task." + property, "desc");
     return this;
   }
 
@@ -129,167 +139,6 @@
     return this;
   }
 
-  protected void applyParameters(Query query) {
-    // assignee parameter
-    if (assignee != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter assignee: " + assignee);
-      }
-      applyParameterWithOperator("assignee", assignee, query);
-    }
-
-    // canidate parameter
-    if (candidate != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter candidateUserId: " + candidate);
-      }
-      query.setString("candidateUserId", candidate);
-
-      if (groupIds != null) {
-        if (log.isDebugEnabled()) {
-          log.debug("setting parameter candidateGroupIds: " + groupIds);
-        }
-        query.setParameterList("candidateGroupIds", groupIds);
-      }
-    }
-
-    // executionId parameter
-    if (executionId != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter executionId: " + executionId);
-      }
-      applyParameterWithOperator("executionId", executionId, query);
-    }
-
-    if (processInstanceId != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter processInstanceId: " + processInstanceId);
-      }
-      applyParameterWithOperator("processInstanceId", processInstanceId, query);
-    }
-
-    if (activityName != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter activityName: " + activityName);
-      }
-      applyParameterWithOperator("activityName", activityName, query);
-    }
-
-    if (processDefinitionId != null) {
-      if (log.isDebugEnabled()) {
-        log.debug("setting parameter processDefinitionId: " + processDefinitionId);
-      }
-      applyParameterWithOperator("processDefinitionId", processDefinitionId, query);
-    }
-  }
-
-  protected String hql() {
-    StringBuilder hql = new StringBuilder();
-    hql.append("select ");
-
-    // participations
-    if (candidate != null) {
-      if (count) {
-        hql.append("count(distinct task.id) ");
-      } else {
-        hql.append("distinct task.id ");
-      }
-
-      hql.append("from ");
-      hql.append(ParticipationImpl.class.getName());
-      hql.append(" as participant join participant.task as task ");
-
-      appendWhereClause("participant.type = 'candidate' ", hql);
-
-      IdentitySession identitySession = EnvironmentImpl.getFromCurrent(IdentitySession.class);
-      List<Group> groups = identitySession.findGroupsByUser(candidate);
-      if (groups.isEmpty()) {
-        groupIds = null;
-        appendWhereClause("participant.userId = :candidateUserId ", hql);
-      }
-      else {
-        groupIds = new ArrayList<String>();
-        for (Group group: groups) {
-          groupIds.add(group.getId());
-        }
-        appendWhereClause("(participant.userId = :candidateUserId or participant.groupId in (:candidateGroupIds))", hql);
-      }
-    }
-    else {
-      if (count) {
-        hql.append("count(task) ");
-      } else {
-        hql.append("task ");
-      }
-
-      hql.append("from ");
-      hql.append(TaskImpl.class.getName());
-      hql.append(" as task ");
-    }
-
-    if (suspended != null) {
-      if (suspended) {
-        appendWhereClause("task.state = '" + ExecutionImpl.STATE_SUSPENDED + "' ", hql);
-      } else {
-        appendWhereClause("task.state != '" + ExecutionImpl.STATE_SUSPENDED + "' ", hql);
-      }
-    }
-
-    if (executionId != null) {
-      appendWhereClauseWithOperator("task.execution.id", "executionId", hql);
-    }
-
-    if (processInstanceId != null) {
-      appendWhereClauseWithOperator("task.processInstance.id", "processInstanceId", hql);
-    }
-
-    if (activityName != null) {
-      appendWhereClauseWithOperator("task.execution.activityName", "activityName", hql);
-    }
-
-    if (processDefinitionId != null) {
-      appendWhereClauseWithOperator("task.processInstance.processDefinitionId", "processDefinitionId", hql);
-    }
-
-    if (assignee != null) {
-      appendWhereClauseWithOperator("task.assignee", "assignee", hql);
-    } else if (unassigned) {
-      appendWhereClause("task.assignee is null ", hql);
-    }
-
-    if (candidate == null && !count)
-      appendOrderByClause(hql);
-
-    String hqlQuery = hql.toString();
-    log.debug(hqlQuery);
-    return hqlQuery;
-  }
-
-  @Override
-  public Object execute(Session session) {
-    Object result = super.execute(session);
-    if (candidate == null || count) return result;
-
-    if (uniqueResult) {
-      if (result == null) return null;
-      return session.get(TaskImpl.class, (Serializable) result);
-    }
-    else {
-      List<?> list = (List<?>) result;
-      if (list.isEmpty()) return Collections.EMPTY_LIST;
-
-      StringBuilder hql = new StringBuilder();
-      hql.append("from ").append(TaskImpl.class.getName()).append(" as task ");
-      isWhereAdded = false;
-      appendWhereClause("task.id in (:identifiers) ", hql);
-      appendOrderByClause(hql);
-
-      return session.createQuery(hql.toString())
-        .setParameterList("identifiers", list)
-        .list();
-    }
-  }
-
   public List<Task> list() {
     return CollectionUtil.checkList(untypedList(), Task.class);
   }
@@ -301,35 +150,103 @@
   public TaskQuery activityName(QueryOperator operator, String... activityName) {
     this.activityName = activityName;
     parameterOperators.put("activityName", operator);
-    
+
     return this;
   }
 
   public TaskQuery assignee(QueryOperator operator, String... userId) {
     this.assignee = userId;
     parameterOperators.put("assignee", operator);
-    
+
     return this;
   }
 
   public TaskQuery executionId(QueryOperator operator, String... executionId) {
     this.executionId = executionId;
     parameterOperators.put("executionId", operator);
-    
+
     return this;
   }
 
   public TaskQuery processDefinitionId(QueryOperator operator, String... processDefinitionId) {
     this.processDefinitionId = processDefinitionId;
     parameterOperators.put("processDefinitionId", operator);
-    
+
     return this;
   }
 
   public TaskQuery processInstanceId(QueryOperator operator, String... processInstanceId) {
     this.processInstanceId = processInstanceId;
     parameterOperators.put("processInstanceId", operator);
-    
+
     return this;
   }
+
+  protected Object execute(QuerySession querySession) throws Exception {
+    QueryProperty queryProperty = new QueryProperty();
+
+    // key
+    queryProperty.setKey(TaskImpl.class.getName());
+
+    // result type
+    if (count) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_COUNT);
+    } else if (uniqueResult) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_UNIQUE);
+    }
+
+    if (page != null) {
+      queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE);
+      queryProperty.setFirstResult(page.firstResult);
+      queryProperty.setMaxResults(page.maxResults);
+      if (count) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_COUNT);
+      } else if (uniqueResult) {
+        queryProperty.setResultType(QueryProperty.RESULT_TYPE_PAGE_UNIQUE);
+      }
+    }
+
+    // conditions
+    if (suspended != null) {
+        if (suspended.equals(Boolean.TRUE)) {
+          queryProperty.addCondition("task.state", ExecutionImpl.STATE_SUSPENDED, QueryOperator.EQUALS);
+        } else {
+          queryProperty.addCondition("task.state", ExecutionImpl.STATE_SUSPENDED, QueryOperator.NOT_EQUALS);
+        }
+    }
+
+    if (assignee != null) {
+      queryProperty.addCondition("task.assignee", assignee, findOperator("assignee"));
+    } else if (unassigned) {
+      queryProperty.addCondition("task.assignee", null, QueryOperator.IS_NULL);
+    }
+
+    if (candidate != null) {
+      queryProperty.addCondition("candidate", candidate, findOperator("candidate"));
+    }
+
+    if (executionId != null) {
+      queryProperty.addCondition("task.execution.id", executionId, findOperator("executionId"));
+    }
+
+    if (processInstanceId != null) {
+      queryProperty.addCondition("task.processInstance.id", processInstanceId, findOperator("processInstanceId"));
+    }
+
+    if (processDefinitionId != null) {
+      queryProperty.addCondition("task.processInstance.processDefinitionId", processDefinitionId, findOperator("processDefinitionId"));
+    }
+
+    if (activityName != null) {
+      queryProperty.addCondition("task.execution.activityName", activityName, findOperator("activityName"));
+    }
+
+    // orders
+    for (Map.Entry<String, String> entry : orders.entrySet()) {
+      queryProperty.addOrder(entry.getKey(), entry.getValue());
+    }
+
+    return querySession.query(queryProperty);
+  }
+
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/ProcessDeployer.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/ProcessDeployer.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/ProcessDeployer.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -28,12 +28,12 @@
 
 import org.jbpm.api.ProcessDefinition;
 import org.jbpm.api.ProcessDefinitionQuery;
+import org.jbpm.api.RepositoryService;
 import org.jbpm.internal.log.Log;
 import org.jbpm.pvm.internal.env.EnvironmentImpl;
 import org.jbpm.pvm.internal.migration.InstanceMigrator;
 import org.jbpm.pvm.internal.migration.MigrationDescriptor;
 import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
-import org.jbpm.pvm.internal.session.RepositorySession;
 import org.jbpm.pvm.internal.xml.Parse;
 import org.jbpm.pvm.internal.xml.Parser;
 
@@ -42,7 +42,7 @@
  * @author Tom Baeyens
  */
 public class ProcessDeployer implements Deployer {
-  
+
   private static final Log log = Log.getLog(ProcessDeployer.class.getName());
 
   protected String extension;
@@ -55,9 +55,9 @@
 
   @SuppressWarnings("unchecked")
   public void deploy(DeploymentImpl deployment) {
-    
+
     for (String resourceName: deployment.getResourceNames()) {
-      
+
       if (resourceName.endsWith(extension)) {
         byte[] bytes = deployment.getBytes(resourceName);
         InputStream inputStream = new ByteArrayInputStream(bytes);
@@ -87,7 +87,7 @@
                 processDefinition.setId(id);
                 processDefinition.setKey(key);
                 processDefinition.setVersion(version.intValue());
-            
+
               } else {
                 checkKey(processDefinition, deployment);
                 checkVersion(processDefinition, deployment);
@@ -96,7 +96,7 @@
                 deployment.setProcessDefinitionId(processDefinitionName, processDefinition.getId());
                 deployment.setProcessDefinitionKey(processDefinitionName, processDefinition.getKey());
                 deployment.setProcessDefinitionVersion(processDefinitionName, new Long(processDefinition.getVersion()));
-                
+
                 //execute migration
                 Map<ProcessDefinition, MigrationDescriptor> migrations = (Map<ProcessDefinition, MigrationDescriptor>)parse.contextMapGet(Parse.CONTEXT_KEY_MIGRATIONS);
                 if (migrations != null) {
@@ -105,7 +105,7 @@
                     InstanceMigrator.migrateAll(processDefinition, migrationDescriptor);
                   }
                 }
-                
+
               }
 
               deployment.addObject(processDefinitionName, processDefinition);
@@ -115,7 +115,7 @@
       }
     }
   }
-  
+
   protected void checkKey(ProcessDefinitionImpl processDefinition, DeploymentImpl deployment) {
     String processDefinitionName = processDefinition.getName();
     String processDefinitionKey = processDefinition.getKey();
@@ -127,26 +127,30 @@
       processDefinitionKey = processDefinitionName.replaceAll("[^\\p{L}\\p{N}]", "_");
       processDefinition.setKey(processDefinitionKey);
     }
-    
-    RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class);
 
-    List<ProcessDefinition> existingProcesses = repositorySession.createProcessDefinitionQuery()
+    List<ProcessDefinition> existingProcesses = EnvironmentImpl.getFromCurrent(RepositoryService.class)
+        .createProcessDefinitionQuery()
         .processDefinitionName(processDefinitionName)
         .list();
-    
+
     for (ProcessDefinition existingProcess: existingProcesses) {
       if (!processDefinitionKey.equals(existingProcess.getKey())) {
-        deployment.addProblem("invalid key '"+processDefinitionKey+"' in process "+processDefinition.getName()+".  Existing process has name '"+processDefinitionName+"' and key '"+existingProcess.getKey()+"'");
+        deployment.addProblem("invalid key '" + processDefinitionKey
+            + "' in process " + processDefinition.getName() + ".  Existing process has name '"
+            + processDefinitionName + "' and key '" + existingProcess.getKey() + "'");
       }
     }
 
-    existingProcesses = repositorySession.createProcessDefinitionQuery()
+    existingProcesses = EnvironmentImpl.getFromCurrent(RepositoryService.class)
+        .createProcessDefinitionQuery()
         .processDefinitionKey(processDefinitionKey)
         .list();
-    
+
     for (ProcessDefinition existingProcess: existingProcesses) {
       if (!processDefinitionName.equals(existingProcess.getName())) {
-        deployment.addProblem("invalid name '"+processDefinitionName+"' in process "+processDefinition.getName()+".  Existing process has name '"+existingProcess.getName()+"' and key '"+processDefinitionKey+"'");
+        deployment.addProblem("invalid name '" + processDefinitionName
+            + "' in process " + processDefinition.getName() + ".  Existing process has name '"
+            + existingProcess.getName() + "' and key '" + processDefinitionKey + "'");
       }
     }
   }
@@ -158,30 +162,29 @@
       if (log.isTraceEnabled()) log.trace("created id '"+id+"' for "+processDefinition);
       processDefinition.setId(id);
     }
-    
-    RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class);
-    ProcessDefinition existingProcessDefinition = repositorySession.createProcessDefinitionQuery()
+
+    ProcessDefinition existingProcessDefinition = EnvironmentImpl.getFromCurrent(RepositoryService.class)
+        .createProcessDefinitionQuery()
         .processDefinitionId(id)
         .uniqueResult();
     if (existingProcessDefinition != null) {
       deployment.addProblem("process '" + id + "' already exists");
     }
   }
-  
+
   protected void checkVersion(ProcessDefinitionImpl processDefinition, DeploymentImpl deployment) {
     int version = processDefinition.getVersion();
     String key = processDefinition.getKey();
     if (version==ProcessDefinitionImpl.UNASSIGNED_VERSION) {
-      RepositorySession repositorySession = EnvironmentImpl.getFromCurrent(RepositorySession.class);
-      
-      ProcessDefinition latestDeployedVersion = repositorySession
+
+      ProcessDefinition latestDeployedVersion = EnvironmentImpl.getFromCurrent(RepositoryService.class)
           .createProcessDefinitionQuery()
           .processDefinitionKey(key)
           .orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION)
           .page(0, 1)
           .uniqueResult();
 
-      if (latestDeployedVersion!=null) {
+      if (latestDeployedVersion != null) {
         version = latestDeployedVersion.getVersion() + 1;
       } else {
         version = 1;

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -29,7 +29,10 @@
 import org.jbpm.api.NewDeployment;
 import org.jbpm.api.ProcessDefinition;
 import org.jbpm.api.ProcessDefinitionQuery;
+import org.jbpm.api.RepositoryService;
 import org.jbpm.internal.log.Log;
+import org.jbpm.pvm.internal.cmd.CommandService;
+import org.jbpm.pvm.internal.env.EnvironmentImpl;
 import org.jbpm.pvm.internal.id.DbidGenerator;
 import org.jbpm.pvm.internal.model.ExecutionImpl;
 import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
@@ -134,7 +137,11 @@
   // queries //////////////////////////////////////////////////////////////////
 
   public ProcessDefinitionQueryImpl createProcessDefinitionQuery() {
-    return new ProcessDefinitionQueryImpl();
+    CommandService commandService = (CommandService) EnvironmentImpl
+        .getFromCurrent(CommandService.NAME_TX_REQUIRED_COMMAND_SERVICE);
+    ProcessDefinitionQueryImpl processDefinitionQueryImpl = new ProcessDefinitionQueryImpl();
+    processDefinitionQueryImpl.setCommandService(commandService);
+    return processDefinitionQueryImpl;
   }
 
   public ProcessDefinitionImpl findProcessDefinitionByKey(String processDefinitionKey) {

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/DbSession.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/DbSession.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/DbSession.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -22,6 +22,7 @@
 package org.jbpm.pvm.internal.session;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.jbpm.api.Execution;
@@ -136,4 +137,8 @@
   List<ExecutionImpl> findExecutionsForResume(Set<String> processDefinitionIds);
   DeploymentProperty findDeploymentPropertyByProcessDefinitionId(String processDefinitionId);
   List<Long> findDeploymentDbids();
+
+  // query
+  Map<String, Number> findAvgDurationPerActivity(String processDefinitionId);
+  Map<String, Number> findChoiceDistribution(String processDefinitionId, String activityName);
 }

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/QuerySession.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/QuerySession.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/session/QuerySession.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.session;
+
+import org.jbpm.api.Deployment;
+import org.jbpm.pvm.internal.query.QueryProperty;
+
+/**
+ * All of query class could use this interface to fetch data from database.
+ *
+ * @author Huisheng Xu
+ */
+public interface QuerySession {
+  Object query(QueryProperty queryProperty);
+}

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/OptimisticLockException.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/OptimisticLockException.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/OptimisticLockException.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.tx;
+
+/**
+ * optimistic lock exception.
+ *
+ * @author Huisheng Xu
+ */
+public class OptimisticLockException {
+}

Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding/QuerySessionBinding.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding/QuerySessionBinding.java	                        (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding/QuerySessionBinding.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.internal.wire.binding;
+
+import org.jbpm.pvm.internal.hibernate.QuerySessionImpl;
+import org.jbpm.pvm.internal.wire.descriptor.ObjectDescriptor;
+import org.jbpm.pvm.internal.xml.Parse;
+import org.jbpm.pvm.internal.xml.Parser;
+import org.w3c.dom.Element;
+
+
+/**
+ * @author Huisheng Xu
+ */
+public class QuerySessionBinding extends WireDescriptorBinding {
+
+  public QuerySessionBinding() {
+    super("query-session");
+  }
+
+  public Object parse(Element element, Parse parse, Parser parser) {
+    ObjectDescriptor objectDescriptor = new ObjectDescriptor(QuerySessionImpl.class);
+    objectDescriptor.setAutoWireEnabled(true);
+    return objectDescriptor;
+  }
+
+}

Modified: jbpm4/trunk/modules/pvm/src/main/resources/jbpm.default.cfg.xml
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/resources/jbpm.default.cfg.xml	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/resources/jbpm.default.cfg.xml	2010-10-08 09:25:57 UTC (rev 6748)
@@ -46,6 +46,7 @@
   <transaction-context>
     <repository-session />
     <db-session />
+    <query-session />
 
     <message-session />
     <timer-session />

Modified: jbpm4/trunk/modules/pvm/src/main/resources/jbpm.wire.bindings.xml
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/resources/jbpm.wire.bindings.xml	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/pvm/src/main/resources/jbpm.wire.bindings.xml	2010-10-08 09:25:57 UTC (rev 6748)
@@ -16,7 +16,7 @@
   <binding class="org.jbpm.pvm.internal.wire.binding.StringBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.NullBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.ClassBinding" />
-  <!-- object and ref --> 
+  <!-- object and ref -->
   <binding class="org.jbpm.pvm.internal.wire.binding.ObjectBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.RefBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.JndiBinding" />
@@ -55,8 +55,9 @@
   <binding class="org.jbpm.pvm.internal.wire.binding.JbossIdmIdentitySessionBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.RepositorySessionBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.MailSessionBinding" />
-  
-  <!-- dynamic type mapping configuration  -->    
+  <binding class="org.jbpm.pvm.internal.wire.binding.QuerySessionBinding" />
+
+  <!-- dynamic type mapping configuration  -->
   <binding class="org.jbpm.pvm.internal.wire.binding.TypesBinding" />
   <!-- services  -->
   <binding class="org.jbpm.pvm.internal.wire.binding.CommandServiceBinding" />
@@ -67,7 +68,7 @@
   <binding class="org.jbpm.pvm.internal.wire.binding.TaskServiceBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.RepositoryServiceBinding" />
   <binding class="org.jbpm.pvm.internal.wire.binding.RepositoryCacheBinding" />
-  
+
   <!-- deployers -->
   <binding class="org.jbpm.pvm.internal.wire.binding.DeployerManagerBinding" />
 
@@ -94,7 +95,7 @@
 
   <!-- jpdl bindings -->
   <binding class="org.jbpm.jpdl.internal.xml.JpdlDeployerBinding" />
-  
+
   <!-- spring bindings -->
   <binding class="org.jbpm.pvm.internal.wire.binding.SpringTransactionInterceptorBinding" />
 

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -39,8 +39,8 @@
  * @author Joram Barrez
  */
 public class TimerStartEventTest extends JbpmTestCase {
-  
-  private static final String INVALID_PROCESS_1 = 
+
+  private static final String INVALID_PROCESS_1 =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='invalidProcess1'>" +
     "    <startEvent id='theStart' >" +
@@ -50,8 +50,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String INVALID_PROCESS_2 = 
+
+  private static final String INVALID_PROCESS_2 =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='invalidProcess1'>" +
     "    <startEvent id='theStart' >" +
@@ -64,8 +64,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String INVALID_PROCESS_3 = 
+
+  private static final String INVALID_PROCESS_3 =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='invalidProcess1'>" +
     "    <startEvent id='theStart' >" +
@@ -77,8 +77,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String INVALID_PROCESS_4 = 
+
+  private static final String INVALID_PROCESS_4 =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='invalidProcess1'>" +
     "    <startEvent id='theStart' >" +
@@ -90,8 +90,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String TIMER_START_FIXED_DUEDATE = 
+
+  private static final String TIMER_START_FIXED_DUEDATE =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='timerStartFixedDueDate'>" +
     "    <startEvent id='theStart' >" +
@@ -105,8 +105,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String TIMER_START_TIMECYCLE_DURATION = 
+
+  private static final String TIMER_START_TIMECYCLE_DURATION =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='timerStartTimeCycleDuration'>" +
     "    <startEvent id='theStart' >" +
@@ -120,8 +120,8 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
-  private static final String TIMER_START_TIMECYCLE_CRON_EXPR = 
+
+  private static final String TIMER_START_TIMECYCLE_CRON_EXPR =
     "<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
     "  <process id='timerStartTimeCycleCronExpression' name='timerStartCron'>" +
     "    <startEvent id='theStart' >" +
@@ -135,20 +135,20 @@
     "    <endEvent id='theEnd' />" +
     "  </process>" +
     "</definitions>";
-  
+
   @Override
   protected void tearDown() throws Exception {
     Clock.setExplicitTime(null);
     super.tearDown();
   }
-  
+
   public void testInvalidProcess() {
     testDeployInvalidProcess(INVALID_PROCESS_1);
     testDeployInvalidProcess(INVALID_PROCESS_2);
     testDeployInvalidProcess(INVALID_PROCESS_3);
     testDeployInvalidProcess(INVALID_PROCESS_4);
   }
-  
+
   private void testDeployInvalidProcess(String process) {
     try {
       deployBpmn2XmlString(process);
@@ -157,107 +157,107 @@
       // Exception is expected
     }
   }
-  
+
   public void testTimerStartEventWithFixedDuedate() {
     deployBpmn2XmlString(TIMER_START_FIXED_DUEDATE);
-    
+
     // After deployment, there should be one job in the database that starts a new process instance
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNotNull(startProcessTimer);
     assertEquals(DateUtils.getDateAtMidnight(10, Calendar.OCTOBER, 2099).getTime(), startProcessTimer.getDueDate().getTime());
-    
+
     ProcessInstanceQuery procInstQuery = executionService.createProcessInstanceQuery()
                             .processDefinitionId(findProcessDefinitionId("timerStartFixedDueDate"));
-    
+
     // Triggering the job should start a new process instance of the deployed process definition
     assertEquals(0, procInstQuery.count());
     managementService.executeJob(startProcessTimer.getId());
     assertEquals(1, procInstQuery.count());
-    
+
     // Since a fixed duedate was used, the job should have been deleted from the database
     startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNull(startProcessTimer);
   }
-  
+
   public void testTimerStartEventWithDurationAsTimeCycle() {
     Clock.setExplicitTime(DateUtils.getDateAtMidnight(10, Calendar.OCTOBER, 2099));
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
-    
+
     // After deployment, there should be one job in the database that starts a new process instance
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNotNull(startProcessTimer);
     assertEquals(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 10, 0, 0).getTime(), startProcessTimer.getDueDate().getTime());
-    
+
     // Triggering the job should start a new process instance of the deployed process definition
     ProcessInstanceQuery procInstQuery = executionService.createProcessInstanceQuery()
                       .processDefinitionId(findProcessDefinitionId("timerStartTimeCycleDuration"));
     assertEquals(0, procInstQuery.count());
-    
+
     // need to change current date to calculate the next duedate internally correctly
-    Clock.setExplicitTime(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 10, 0, 0)); 
+    Clock.setExplicitTime(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 10, 0, 0));
     managementService.executeJob(startProcessTimer.getId());
     assertEquals(1, procInstQuery.count());
-    
+
     // Since a timeCycle was used, the job should have been recreated with a new duedate
     startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertEquals(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 20, 0, 0).getTime(), startProcessTimer.getDueDate().getTime());
-    
-    
+
+
     // So we need to manually delete it
     managementService.deleteJob(Long.valueOf(startProcessTimer.getId()));
   }
-  
+
   public void testTimerStartEventWithCronExpressionAsTimeCycle() {
     Clock.setExplicitTime(DateUtils.getDateAtMidnight(10, Calendar.OCTOBER, 2099));
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_CRON_EXPR);
-    
+
     // After deployment, there should be one job in the database that starts a new process instance
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNotNull(startProcessTimer);
     assertEquals(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 22, 0, 0).getTime(), startProcessTimer.getDueDate().getTime());
-    
+
     // Triggering the job should start a new process instance of the deployed process definition
     ProcessInstanceQuery procInstQuery = executionService.createProcessInstanceQuery()
                       .processDefinitionId(findProcessDefinitionId("timerStartTimeCycleCronExpression"));
     assertEquals(0, procInstQuery.count());
-    
+
     // need to change current date to calculate the next duedate correctly
-    Clock.setExplicitTime(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 22, 0, 0)); 
+    Clock.setExplicitTime(DateUtils.getDate(10, Calendar.OCTOBER, 2099, 22, 0, 0));
     managementService.executeJob(startProcessTimer.getId());
     assertEquals(1, procInstQuery.count());
-    
+
     // Since a timeCycle was used, the job should have been recreated with a new duedate
     startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertEquals(DateUtils.getDate(11, Calendar.OCTOBER, 2099, 22, 0, 0).getTime(), startProcessTimer.getDueDate().getTime());
-    
+
     // So we need to manually delete it
     managementService.deleteJob(Long.valueOf(startProcessTimer.getId()));
   }
-  
+
   public void testDeleteProcessDefinitionBeforeTimerTriggers() {
     Clock.setExplicitTime(DateUtils.getDateAtMidnight(10, Calendar.OCTOBER, 2099));
     String deployId = deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
-    
+
     // Delete the process definition
     String procDefId = findProcessDefinitionId("timerStartTimeCycleDuration");
     repositoryService.deleteDeploymentCascade(deployId);
     registeredDeployments.remove(0);
-    
+
     // After process definition deletion, the timer is still in the database
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNotNull(startProcessTimer);
-    
+
     // When the timer triggers, it notices that the process definition is gone and it deletes itselves
     // No new process instance should have been started
     ProcessInstanceQuery procInstQuery = executionService.createProcessInstanceQuery().processDefinitionId(procDefId);
     assertEquals(0, procInstQuery.count());
-    
+
     managementService.executeJob(startProcessTimer.getId());
     startProcessTimer = managementService.createJobQuery().uniqueResult();
     assertNull(startProcessTimer);
     assertEquals(0, procInstQuery.count());
   }
-  
+
   /*
    * Processes with a timer start event should be createable through the executionService.
    */
@@ -265,48 +265,48 @@
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
     ProcessInstance pi = executionService.startProcessInstanceByKey("timerStartTimeCycleDuration");
     assertNotNull(pi);
-    
+
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
     managementService.deleteJob(Long.valueOf(startProcessTimer.getId()));
   }
-  
+
   public void testOnlyOneStartProcessActiveAfterRedeploy() {
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
     List<Job> startProcessTimers = managementService.createJobQuery().list();
     assertEquals(1, startProcessTimers.size());
     String firstJobId = startProcessTimers.get(0).getId();
-    
+
     // Redeploy -> first job should be deleted
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
     assertEquals(2, repositoryService.createProcessDefinitionQuery().list().size());
     startProcessTimers = managementService.createJobQuery().list();
     assertEquals(1, startProcessTimers.size());
-    
+
     String secondJobId = startProcessTimers.get(0).getId();
     assertTrue(!firstJobId.equals(secondJobId));
-    
+
     managementService.deleteJob(Long.valueOf(secondJobId));
   }
-  
+
   public void testLatestProcessDefinitionUsedAfterRedeploy() {
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
     Job startProcessTimer = managementService.createJobQuery().uniqueResult();
-    
-    // Redeploy 
+
+    // Redeploy
     deployBpmn2XmlString(TIMER_START_TIMECYCLE_DURATION);
     List<ProcessDefinition> procDefs = repositoryService.createProcessDefinitionQuery()
                                           .orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION).list();
     assertEquals(2, procDefs.size());
-    
+
     // Firing start process timer -> new process instance for latests version of proc def
     startProcessTimer = managementService.createJobQuery().uniqueResult();
     managementService.executeJob(startProcessTimer.getId());
     ProcessInstance procInst = executionService.createProcessInstanceQuery().uniqueResult();
     assertEquals(procDefs.get(1).getId(), procInst.getProcessDefinitionId());
-    
+
     managementService.deleteJob(Long.valueOf(startProcessTimer.getId()));
   }
-  
+
   private String findProcessDefinitionId(String processDefinitionKey) {
     return repositoryService.createProcessDefinitionQuery()
               .processDefinitionName(processDefinitionKey).uniqueResult().getId();

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/forkjoin/ForkResultsInNullEndActivityTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/forkjoin/ForkResultsInNullEndActivityTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/forkjoin/ForkResultsInNullEndActivityTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -35,37 +35,37 @@
  * @author Huisheng Xu
  */
 public class ForkResultsInNullEndActivityTest extends JbpmTestCase {
-    public static final String XML_FORK_JOIN = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
-        "<process name=\"ForkTest\" xmlns=\"http://jbpm.org/4.3/jpdl\">\n" +
-        "  <start name=\"preparing test\">\n" +
+    public static final String XML_FORK_JOIN =
+        "<process name='ForkTest'>" +
+        "  <start name='preparing test'>" +
         "    <on event='end'>" +
-        "      <event-listener class='org.jbpm.test.activity.forkjoin.ForkResultsInNullEndActivityTest$StartEventListener'/>" +
+        "      <event-listener class='" + StartEventListener.class.getName() + "'/>" +
         "    </on>" +
-        "    <transition to=\"fork\"/>\n" +
-        "  </start>\n" +
-        "  <fork name=\"fork\">\n" +
-        "    <transition to=\"state1\"/>\n" +
-        "    <transition to=\"state2\"/>\n" +
-        "    <transition to=\"cancel\"/>\n" +
-        "  </fork>\n" +
-        "  <state name=\"cancel\">\n" +
-        "    <transition to=\"cancelled\"/>\n" +
-        "  </state>\n" +
-        "  <state name=\"state1\">\n" +
-        "    <transition to=\"states completed\"/>\n" +
-        "  </state>\n" +
-        "  <state name=\"state2\">\n" +
-        "    <transition to=\"states completed\"/>\n" +
-        "  </state>\n" +
-        "  <join multiplicity=\"2\" name=\"states completed\">\n" +
-        "    <transition to=\"completed\"/>\n" +
-        "  </join>\n" +
-        "  <end name=\"cancelled\"/>\n" +
-        "  <end name=\"completed\"/>\n" +
+        "    <transition to='fork'/>" +
+        "  </start>" +
+        "  <fork name='fork'>" +
+        "    <transition to='state1'/>" +
+        "    <transition to='state2'/>" +
+        "    <transition to='cancel'/>" +
+        "  </fork>" +
+        "  <state name='cancel'>" +
+        "    <transition to='cancelled'/>" +
+        "  </state>" +
+        "  <state name='state1'>" +
+        "    <transition to='states completed'/>" +
+        "  </state>" +
+        "  <state name='state2'>" +
+        "    <transition to='states completed'/>" +
+        "  </state>" +
+        "  <join multiplicity='2' name='states completed'>" +
+        "    <transition to='completed'/>" +
+        "  </join>" +
+        "  <end name='cancelled'/>" +
+        "  <end name='completed'/>" +
         "</process>";
 
     public static final String XML_SUB_PROCESS = "" +
-        "<process name='sub_process' xmlns='http://jbpm.org/4.3/jpdl'>" +
+        "<process name='sub_process'>" +
         "  <start>" +
         "    <transition to='sub'/>" +
         "  </start>" +

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -59,19 +59,27 @@
     deleteCascade(deploymentIds);
   }
 
-  private static void assertDeploymentsPresent(List<Deployment> deployments,
-    String... deploymentNames) {
-    assertEquals(deploymentNames.length, deployments.size());
-
-    for (Deployment deployment : deployments) {
-      assert Arrays.binarySearch(deploymentNames, deployment.getName()) >= 0 : deployment.getName();
-    }
-  }
-
   public void testOrderByTimeStamp() {
     testOrderByNaturalOrdening(DeploymentQuery.PROPERTY_TIMESTAMP, 3);
   }
 
+  public void testOrderByState() {
+    String[] deploymentIds = deployTestProcesses();
+
+    List<Deployment> deploymentsAsc = repositoryService.createDeploymentQuery()
+      .orderAsc("name")
+      .list();
+
+    List<Deployment> deploymentsDesc = repositoryService.createDeploymentQuery()
+      .orderDesc("name")
+      .list();
+
+    assertEquals("Claim", deploymentsAsc.get(0).getName());
+    assertEquals("Claim", deploymentsDesc.get(2).getName());
+
+    deleteCascade(deploymentIds);
+  }
+
   public void testCount() {
     String[] deploymentIds = deployTestProcesses();
 
@@ -138,10 +146,20 @@
     deleteCascade(deploymentIds);
   }
 
+  // ~ ========================================================================
   /* --------------
    * HELPER METHODS
    * -------------- */
 
+  private static void assertDeploymentsPresent(List<Deployment> deployments,
+    String... deploymentNames) {
+    assertEquals(deploymentNames.length, deployments.size());
+
+    for (Deployment deployment : deployments) {
+      assert Arrays.binarySearch(deploymentNames, deployment.getName()) >= 0 : deployment.getName();
+    }
+  }
+
   private void deleteCascade(String[] deploymentIds) {
     for (String deploymentId : deploymentIds) {
       repositoryService.deleteDeploymentCascade(deploymentId);

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryActivityInstanceQueryTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryActivityInstanceQueryTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryActivityInstanceQueryTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -42,7 +42,7 @@
  * @author Tom Baeyens
  */
 public class HistoryActivityInstanceQueryTest extends JbpmTestCase {
-  
+
   protected void tearDown() throws Exception {
     Clock.setExplicitTime(null);
     super.tearDown();
@@ -50,26 +50,26 @@
 
   public void testSimpleQuery() {
     deployStartAndSignalTestProcesses();
-    
+
     List<HistoryActivityInstance> histActInsts = historyService.createHistoryActivityInstanceQuery()
       .activityName("a")
       .list();
-    
+
     assertEquals(4, histActInsts.size());
 
     histActInsts = historyService.createHistoryActivityInstanceQuery()
       .activityName("b")
       .list();
-    
+
     assertEquals(3, histActInsts.size());
 
     histActInsts = historyService.createHistoryActivityInstanceQuery()
       .activityName("c")
       .list();
-    
+
     assertEquals(2, histActInsts.size());
   }
-  
+
   // Test for JBPM-2649
   public void testQueryByProcessDefinitionId() {
     String procDefId = deployTestProcess();
@@ -94,102 +94,102 @@
     assertEquals(new Integer(3), activityCounts.get("b"));
     assertEquals(new Integer(2), activityCounts.get("c"));
   }
-  
+
   // Currently only verifies the size of the result set
   public void testQueryByExecutionId() {
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().executionId(ids.get(0)).list().size());
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().executionId(ids.get(1)).list().size());
     assertEquals(2, historyService.createHistoryActivityInstanceQuery().executionId(ids.get(2)).list().size());
     assertEquals(1, historyService.createHistoryActivityInstanceQuery().executionId(ids.get(3)).list().size());
   }
-  
+
   public void testQueryByExecutionIdLike() {
     deployStartAndSignalTestProcesses();
-    
+
     assertEquals(9, historyService.createHistoryActivityInstanceQuery()
       .executionId(QueryOperator.LIKE, "abc%")
       .count());
   }
-  
+
   public void testQueryByExecutionIdIn() {
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(6, historyService.createHistoryActivityInstanceQuery()
       .executionId(QueryOperator.IN, ids.get(0), ids.get(1))
       .count());
   }
-  
+
   public void testQueryByExecutionIdNotIn() {
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(3, historyService.createHistoryActivityInstanceQuery()
       .executionId(QueryOperator.NOT_IN, ids.get(0), ids.get(1))
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdLike() {
     deployStartAndSignalTestProcesses();
-    
+
     assertEquals(9, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.LIKE, "abc%")
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdIn() {
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(6, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.IN, ids.get(0), ids.get(1))
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdNotIn() {
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(3, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.NOT_IN, ids.get(0), ids.get(1))
       .count());
   }
-  
+
   public void testQueryByProcessDefinitionIdLike() {
     deployStartAndSignalTestProcesses();
     deployTestProcessWithTask();
     generateHistoryForTestProcessWithTask();
     deployTestProcessWithTask();
-    
+
     assertEquals(12, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.LIKE, "abc%")
       .count());
   }
-  
+
   public void testQueryByProcessDefinitionIdIn() {
     deployStartAndSignalTestProcesses();
     deployTestProcessWithTask();
     List<String> idsTask = generateHistoryForTestProcessWithTask();
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(6, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.IN, ids.get(0), idsTask.get(0))
       .count());
   }
-  
+
   public void testQueryByProcessDefinitionIdNotIn() {
     deployStartAndSignalTestProcesses();
     deployTestProcessWithTask();
     List<String> idsTask = generateHistoryForTestProcessWithTask();
     List<String> ids = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(15, historyService.createHistoryActivityInstanceQuery()
       .processInstanceId(QueryOperator.NOT_IN, ids.get(0), idsTask.get(0))
       .count());
   }
-  
+
   // Currently only verifies the size of the result set
   public void testQueryByStartedAfter() {
     deployTestProcess();
-    
+
     // start 8 processes (18 activity instances) on simulated time 3000000
     Clock.setExplicitTime(new Date(3000000));
     generateHistoryForTestProcess();
@@ -198,15 +198,15 @@
     // start another 4 processes (9 activity instances) on simulated time 3005000
     Clock.setExplicitTime(new Date(3005000));
     generateHistoryForTestProcess();
-    
+
     Date timeStamp = new Date(3003000);
     assertEquals(9, historyService.createHistoryActivityInstanceQuery().startedAfter(timeStamp).list().size());
   }
-  
+
   // Currently only verifies the size of the result set
   public void testQueryByStartedBefore() {
     deployTestProcess();
-    
+
     // start 4 processes (9 activity instances) on simulated time 3000000
     Clock.setExplicitTime(new Date(3000000));
     generateHistoryForTestProcess();
@@ -215,11 +215,12 @@
     Clock.setExplicitTime(new Date(3002000));
     generateHistoryForTestProcess();
     generateHistoryForTestProcess();
-    
+
     Date timeStamp = new Date(3001000);
+
     assertEquals(9, historyService.createHistoryActivityInstanceQuery().startedBefore(timeStamp).list().size());
   }
-  
+
   //Currently only verifies the size of the result set
   public void testQueryByActivityName() {
     deployStartAndSignalTestProcesses();
@@ -227,68 +228,68 @@
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().activityName("b").list().size());
     assertEquals(2, historyService.createHistoryActivityInstanceQuery().activityName("c").list().size());
   }
-  
+
   public void testQueryByActivityNameLike() {
     deployStartAndSignalTestProcesses();
     assertEquals(9, historyService.createHistoryActivityInstanceQuery()
       .activityName(QueryOperator.LIKE, "%")
       .count());
   }
-  
+
   public void testQueryByActivityNameIn() {
     deployStartAndSignalTestProcesses();
     assertEquals(6, historyService.createHistoryActivityInstanceQuery()
       .activityName(QueryOperator.IN, "a", "c")
       .count());
   }
-  
+
   public void testQueryByActivityNameNotIn() {
     deployStartAndSignalTestProcesses();
     assertEquals(2, historyService.createHistoryActivityInstanceQuery()
       .activityName(QueryOperator.NOT_IN, "a", "b")
       .count());
   }
-  
+
   //Currently only verifies the size of the result set
   public void testQueryByTookLessThen() {
     deployStartAndSignalTestProcesses();
     assertEquals(9, historyService.createHistoryActivityInstanceQuery().tookLessThen(60*60*1000).list().size());
   }
-  
+
   public void testOrderByActivityName() {
     testOrderBy(HistoryActivityInstanceQuery.PROPERTY_ACTIVITYNAME, Arrays.asList("a", "a", "a", "a", "b", "b", "b", "c", "c"));
   }
-  
+
   public void testOrderByStartTime() {
     testOrderByNaturalOrdening(HistoryActivityInstanceQuery.PROPERTY_STARTTIME, 9);
   }
-  
+
   public void testOrderByEndTime() {
     testOrderByNaturalOrdening(HistoryActivityInstanceQuery.PROPERTY_ENDTIME, 9);
   }
-  
+
   public void testOrderByDuration() {
     testOrderByNaturalOrdening(HistoryActivityInstanceQuery.PROPERTY_DURATION, 9);
   }
-  
+
   public void testOrderByExecutionId() {
     testOrderByNaturalOrdening(HistoryActivityInstanceQuery.PROPERTY_EXECUTIONID, 9);
   }
-  
+
   public void testCount() {
     List<String> procInstIds = deployStartAndSignalTestProcesses();
-    
+
     assertEquals(9, historyService.createHistoryActivityInstanceQuery().count());
     assertEquals(4, historyService.createHistoryActivityInstanceQuery().activityName("a").count());
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().activityName("b").count());
     assertEquals(2, historyService.createHistoryActivityInstanceQuery().activityName("c").count());
     assertEquals(0, historyService.createHistoryActivityInstanceQuery().activityName("d").count());
-    
+
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().executionId(procInstIds.get(0)).count());
     assertEquals(3, historyService.createHistoryActivityInstanceQuery().executionId(procInstIds.get(1)).count());
     assertEquals(2, historyService.createHistoryActivityInstanceQuery().executionId(procInstIds.get(2)).count());
     assertEquals(1, historyService.createHistoryActivityInstanceQuery().executionId(procInstIds.get(3)).count());
-    
+
     assertEquals(1, historyService.createHistoryActivityInstanceQuery()
                                   .executionId(procInstIds.get(0)).activityName("a").count());
     assertEquals(1, historyService.createHistoryActivityInstanceQuery()
@@ -296,23 +297,23 @@
     assertEquals(1, historyService.createHistoryActivityInstanceQuery()
             .executionId(procInstIds.get(0)).activityName("c").count());
   }
-  
+
   /**
    * Generates some history data.
-   * 
+   *
    * Calling this method will produce (in this order):
    *   - 1 ended process instance (signalled state a,b,c)
    *   - 1 process instance in state c (signalled a,b)
    *   - 1 process instance in state b (signalled a)
    *   - 1 process instance in state a (just started)
-   *   
+   *
    *   (in this exact order!)
    */
   private List<String> deployStartAndSignalTestProcesses() {
     deployTestProcess();
     return generateHistoryForTestProcess();
   }
-  
+
   /**
    * Returns deployment db id
    */
@@ -338,7 +339,7 @@
 
   private List<String> generateHistoryForTestProcess() {
     List<String> ids = new ArrayList<String>();
-    
+
     ProcessInstance processInstance = executionService.startProcessInstanceByKey("abc");
     executionService.signalExecutionById(processInstance.getId());
     executionService.signalExecutionById(processInstance.getId());
@@ -356,10 +357,10 @@
 
     processInstance = executionService.startProcessInstanceByKey("abc");
     ids.add(processInstance.getId());
-    
+
     return ids;
   }
-  
+
   private void testOrderBy(String property, List<?> expectedValues) {
     testOrderBy(property, expectedValues, null, false);
   }
@@ -367,25 +368,25 @@
   private void testOrderByNaturalOrdening(String property, int expectedNrOfResults) {
     testOrderBy(property, null, expectedNrOfResults, true);
   }
-  
-  private void testOrderBy(String property, List<?> expectedValues, 
+
+  private void testOrderBy(String property, List<?> expectedValues,
           Integer expectedNrOfResults, boolean naturalOrderCheck) {
-    
+
     deployStartAndSignalTestProcesses();
 
-    List<HistoryActivityInstance> listAsc = 
+    List<HistoryActivityInstance> listAsc =
       historyService.createHistoryActivityInstanceQuery().orderAsc(property).list();
-    
-    List<HistoryActivityInstance> listDesc = 
+
+    List<HistoryActivityInstance> listDesc =
       historyService.createHistoryActivityInstanceQuery().orderDesc(property).list();
 
     if (naturalOrderCheck) {
-      QueryAssertions.assertOrderIsNatural(HistoryActivityInstance.class, property, listAsc, listDesc, expectedNrOfResults);      
+      QueryAssertions.assertOrderIsNatural(HistoryActivityInstance.class, property, listAsc, listDesc, expectedNrOfResults);
     } else {
       QueryAssertions.assertOrderOnProperty(HistoryActivityInstance.class, property, listAsc, listDesc, expectedValues);
     }
   }
-  
+
   /**
    * Deploys example process to test history by process instance and execution id.
    * Task has a timer which will append name of the task to the execution id causing
@@ -413,20 +414,20 @@
             "</process>"
           );
   }
-  
+
   private List<String> generateHistoryForTestProcessWithTask() {
     List<String> ids = new ArrayList<String>();
-    
+
     ProcessInstance processInstance = executionService.startProcessInstanceByKey("abcd");
     executionService.signalExecutionById(processInstance.getId());
-    
+
     taskService.completeTask(taskService.findPersonalTasks("alex").get(0).getId());
     executionService.signalExecutionById(processInstance.getId());
     ids.add(processInstance.getId());
 
     return ids;
   }
-  
+
   public void testQueryByProcessInstanceId() {
     deployTestProcessWithTask();
     List<String> ids = generateHistoryForTestProcessWithTask();
@@ -434,21 +435,21 @@
       .createHistoryActivityInstanceQuery()
       .processInstanceId(ids.get(0))
       .orderAsc("id").list();
-    
+
     //first check size of history entries
     assertEquals(3, history.size());
-    
+
     // next check activity names
     assertEquals("a", history.get(0).getActivityName());
     assertEquals("b", history.get(1).getActivityName());
     assertEquals("c", history.get(2).getActivityName());
-    
+
     // last check execution ids to illustrate that for task with timer it is not same as process instance id
     assertEquals(ids.get(0), history.get(0).getExecutionId());
     assertTrue(history.get(1).getExecutionId().startsWith(ids.get(0) + ".b."));
     assertEquals(ids.get(0), history.get(2).getExecutionId());
   }
-  
+
   public void testQueryByExecutionIdMissingTask() {
     deployTestProcessWithTask();
     List<String> ids = generateHistoryForTestProcessWithTask();
@@ -456,12 +457,12 @@
       .createHistoryActivityInstanceQuery()
       .executionId(ids.get(0))
       .orderAsc("id").list();
-    
+
     // check size of history entries
     assertEquals(2, history.size());
     // next check activity names - missing task node
     assertEquals("a", history.get(0).getActivityName());
     assertEquals("c", history.get(1).getActivityName());
   }
-  
+
 }

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryProcessInstanceQueryTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryProcessInstanceQueryTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/HistoryProcessInstanceQueryTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -20,7 +20,7 @@
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 /**
- * 
+ *
  */
 package org.jbpm.test.query;
 
@@ -87,7 +87,7 @@
         .count());
     }
   }
-  
+
   public void testQueryByProcessInstanceIdLike() {
     createTestHistoryProcessInstances(7);
 
@@ -95,7 +95,7 @@
       .processInstanceId(QueryOperator.LIKE, "theProcess%")
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdIn() {
     List<String> procInstIds = createTestHistoryProcessInstances(7);
 
@@ -103,7 +103,7 @@
       .processInstanceId(QueryOperator.IN, procInstIds.get(0), procInstIds.get(1))
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdNotIn() {
     List<String> procInstIds = createTestHistoryProcessInstances(7);
 
@@ -111,7 +111,7 @@
       .processInstanceId(QueryOperator.NOT_IN, procInstIds.get(0), procInstIds.get(1))
       .count());
   }
-  
+
   public void testQueryByProcessInstanceKeyLike() {
     createTestHistoryProcessInstances(7);
 
@@ -119,7 +119,7 @@
       .processInstanceKey(QueryOperator.LIKE, "theProcess-%")
       .count());
   }
-  
+
   public void testQueryByProcessInstanceKeyIn() {
     createTestHistoryProcessInstances(7);
 
@@ -127,7 +127,7 @@
       .processInstanceKey(QueryOperator.IN, "theProcess-1", "theProcess-5")
       .count());
   }
-  
+
   public void testQueryByProcessInstanceKeyNotIn() {
     createTestHistoryProcessInstances(7);
 
@@ -135,7 +135,7 @@
       .processInstanceKey(QueryOperator.NOT_IN, "theProcess-1", "theProcess-5", "theProcess-6")
       .count());
   }
-  
+
   public void testQueryByInitiator() {
     deployJpdlXmlString("<process name='theProcess'>"
             + "  <start>"
@@ -161,7 +161,7 @@
     assertEquals(1, historyService.createHistoryProcessInstanceQuery().initiator("mike").count());
     assertEquals(1, historyService.createHistoryProcessInstanceQuery().initiator("alex").count());
   }
-  
+
   public void testQueryByInitiatorLike() {
     deployJpdlXmlString("<process name='theProcess'>"
             + "  <start>"
@@ -242,6 +242,7 @@
     List<HistoryProcessInstance> procInsts = historyService.createHistoryProcessInstanceQuery()
       .endedBefore(yesterday)
       .list();
+
     assertEquals(1, procInsts.size());
 
     HistoryProcessInstance endedTwoDaysAgoProcInst = procInsts.get(0);
@@ -301,7 +302,7 @@
     calendar.add(Calendar.DATE, 1);
     Date yesterday = calendar.getTime();
     Clock.setExplicitTime(yesterday);
-    
+
     // end the second process instance one day before
     String endedYesterdayProcInstId = procInstIds.get(1);
     executionService.endProcessInstance(endedYesterdayProcInstId, "ended");

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/ProcessInstanceQueryTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/ProcessInstanceQueryTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/ProcessInstanceQueryTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -36,10 +36,10 @@
 import org.jbpm.test.JbpmTestCase;
 
 public class ProcessInstanceQueryTest extends JbpmTestCase {
-  
+
   private static final String TEST_PROCESS_1_KEY = "testProcess1";
-  
-  private static final String TEST_PROCESS_1 = 
+
+  private static final String TEST_PROCESS_1 =
     "<process name='" + TEST_PROCESS_1_KEY + "'>" +
     "  <start>" +
     "    <transition to='a' />" +
@@ -49,10 +49,10 @@
     "  </state>" +
     "  <end name='end' />" +
     "</process>";
-  
+
   private static final String TEST_PROCESS_2_KEY = "testProcess2";
-  
-  private static final String TEST_PROCESS_2 = 
+
+  private static final String TEST_PROCESS_2 =
     "<process name='" + TEST_PROCESS_2_KEY + "'>" +
     "  <start>" +
     "    <transition to='f' />" +
@@ -72,25 +72,25 @@
     "  </join>" +
     "  <end name='end' />" +
     "</process>";
-  
+
   public void testQueryByProcessInstanceId() {
     Map<String, ArrayList<String>> processInstanceIds = startTestProcesses(3, 7);
     List<String> idsForTestProcess1 = processInstanceIds.get(TEST_PROCESS_1_KEY);
     List<String> idsForTestProcess2 = processInstanceIds.get(TEST_PROCESS_2_KEY);
-    
+
     for (String processInstanceId : idsForTestProcess1) {
       ProcessInstance pi = executionService.createProcessInstanceQuery()
         .processInstanceId(processInstanceId).uniqueResult();
       assertNotNull(pi);
     }
-    
+
     for (String processInstanceId : idsForTestProcess2) {
       ProcessInstance pi = executionService.createProcessInstanceQuery()
         .processInstanceId(processInstanceId).uniqueResult();
       assertNotNull(pi);
     }
   }
-  
+
   public void testQueryByProcessInstanceKey() {
     startTestProcesses(7, 8);
 
@@ -99,73 +99,79 @@
         .processInstanceKey(TEST_PROCESS_1_KEY + "-" + i).uniqueResult();
       assertNotNull(pi);
     }
-    
+
     for (int i = 0; i < 8; i++) {
       ProcessInstance pi = executionService.createProcessInstanceQuery()
         .processInstanceKey(TEST_PROCESS_2_KEY + "-" + i).uniqueResult();
       assertNotNull(pi);
     }
   }
-  
+
   public void testQueryByProcessDefinitionId() {
     startTestProcesses(10, 6);
-    ProcessDefinition definitionProcess1 = 
+    ProcessDefinition definitionProcess1 =
       repositoryService.createProcessDefinitionQuery().processDefinitionKey(TEST_PROCESS_1_KEY).uniqueResult();
-    ProcessDefinition definitionProcess2 = 
+    ProcessDefinition definitionProcess2 =
       repositoryService.createProcessDefinitionQuery().processDefinitionKey(TEST_PROCESS_2_KEY).uniqueResult();
-    
-    List<ProcessInstance> processInstances = 
+
+    List<ProcessInstance> processInstances =
       executionService.createProcessInstanceQuery().processDefinitionId(definitionProcess1.getId()).list();
     assertEquals(10, processInstances.size());
-    
-    processInstances = 
+
+    processInstances =
       executionService.createProcessInstanceQuery().processDefinitionId(definitionProcess2.getId()).list();
     assertEquals(6, processInstances.size());
   }
-  
+
   public void testQueryBySuspended() {
     startTestProcesses(6, 0); // Don't start any instance of test process 2
-    
+
     Deployment deployment = repositoryService.createDeploymentQuery().uniqueResult();
     repositoryService.suspendDeployment(deployment.getId());
-    
+
     List<ProcessInstance> processInstances = executionService.createProcessInstanceQuery().suspended().list();
     assertEquals(6, processInstances.size());
   }
-  
+
   public void testQueryByNotSuspended() {
     startTestProcesses(5, 5);
-    
+
     ProcessInstanceQuery query = executionService.createProcessInstanceQuery().notSuspended();
     List<ProcessInstance> processInstances = query.list();
     assertEquals(10, processInstances.size());
-    
+
     List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
     assertEquals(2, deployments.size());
     repositoryService.suspendDeployment(deployments.get(0).getId());
-    
+
     processInstances = query.list();
     assertEquals(5, processInstances.size());
   }
-  
+
   public void testQueryByPage() {
     startTestProcesses(8, 12);
-    
+
     for (int i = 0; i < 20; i += 2) {
       List<ProcessInstance> processInstances = executionService.createProcessInstanceQuery().page(i, 2).list();
       assertEquals(2, processInstances.size());
     }
   }
-  
+
+  public void testQueryWithPageAndUnique() {
+    startTestProcesses(8, 12);
+    ProcessInstance processInstance = executionService.createProcessInstanceQuery().page(0, 1).uniqueResult();
+    assertNotNull(processInstance);
+  }
+
   public void testOrderByAscKey() {
     startTestProcesses(6, 10);
-    
-    List<ProcessInstance> processInstances = 
+
+    List<ProcessInstance> processInstances =
       executionService.createProcessInstanceQuery().orderAsc(ProcessInstanceQuery.PROPERTY_KEY).list();
     assertEquals(16, processInstances.size());
-    
+
     for (int i = 0; i < processInstances.size(); i++) {
-      
+
       if (i < 6 ) {
         assertTrue(processInstances.get(i).getKey().startsWith(TEST_PROCESS_1_KEY));
       } else {
@@ -173,16 +179,16 @@
       }
     }
   }
-  
+
   public void testOrderByDescKey() {
     startTestProcesses(5, 9);
-    
-    List<ProcessInstance> processInstances = 
+
+    List<ProcessInstance> processInstances =
       executionService.createProcessInstanceQuery().orderDesc(ProcessInstanceQuery.PROPERTY_KEY).list();
     assertEquals(14, processInstances.size());
-    
+
     for (int i = 0; i < processInstances.size(); i++) {
-      
+
       if (i < 9 ) {
         assertTrue(processInstances.get(i).getKey().startsWith(TEST_PROCESS_2_KEY));
       } else {
@@ -194,158 +200,158 @@
   public void testCount() {
     Map<String, ArrayList<String>> processInstanceIds = startTestProcesses(4, 6);
     List<String> idsForTestProcess1 = processInstanceIds.get(TEST_PROCESS_1_KEY);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     for (String processInstanceId : idsForTestProcess1) {
       assertEquals(1, executionService.createProcessInstanceQuery().processInstanceId(processInstanceId).count());
     }
-    
+
     for (int i = 0; i < 6; i++) {
       assertEquals(1, executionService.createProcessInstanceQuery().processInstanceKey(TEST_PROCESS_2_KEY + "-" + i).count());
     }
-    
+
     try {
       executionService.createProcessInstanceQuery().page(0, 3).count();
       fail("expected exception");
     } catch (JbpmException e) {  }
   }
 
-  
+
   public void testProcessInstanceLike() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(4, executionService.createProcessInstanceQuery().processInstanceId(QueryOperator.LIKE, "testProcess1.%").count());
-    
+
     assertEquals(6, executionService.createProcessInstanceQuery().processInstanceId(QueryOperator.LIKE, "testProcess2.%").count());
   }
-  
+
   public void testProcessDefinitionLike() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().processDefinitionId(QueryOperator.LIKE, "testProcess%").count());
   }
-  
+
   public void testProcessInstanceKeyLike() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(4, executionService.createProcessInstanceQuery().processInstanceKey(QueryOperator.LIKE, "testProcess1-%").count());
   }
-  
+
   public void testProcessInstanceIn() {
     Map<String, ArrayList<String>> processInstanceIds = startTestProcesses(4, 6);
     List<String> idsForTestProcess1 = processInstanceIds.get(TEST_PROCESS_1_KEY);
     List<String> idsForTestProcess2 = processInstanceIds.get(TEST_PROCESS_2_KEY);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(2, executionService.createProcessInstanceQuery()
       .processInstanceId(QueryOperator.IN, idsForTestProcess1.get(0), idsForTestProcess1.get(1))
       .count());
-    
+
     assertEquals(2, executionService.createProcessInstanceQuery()
       .processInstanceId(QueryOperator.IN, idsForTestProcess2.get(0), idsForTestProcess2.get(1))
       .count());
   }
-  
+
   public void testProcessDefinitionIn() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(4, executionService.createProcessInstanceQuery()
       .processDefinitionId(QueryOperator.IN, "testProcess1-1", "testProcess2")
       .count());
   }
-  
+
   public void testProcessInstanceKeyIn() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(2, executionService.createProcessInstanceQuery()
       .processInstanceKey(QueryOperator.IN, "testProcess1-0", "testProcess1-1")
       .count());
   }
-  
+
   public void testProcessInstanceNotIn() {
     Map<String, ArrayList<String>> processInstanceIds = startTestProcesses(4, 6);
     List<String> idsForTestProcess1 = processInstanceIds.get(TEST_PROCESS_1_KEY);
     List<String> idsForTestProcess2 = processInstanceIds.get(TEST_PROCESS_2_KEY);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(8, executionService.createProcessInstanceQuery()
       .processInstanceId(QueryOperator.NOT_IN, idsForTestProcess1.get(0), idsForTestProcess1.get(1))
       .count());
-    
+
     assertEquals(8, executionService.createProcessInstanceQuery()
       .processInstanceId(QueryOperator.NOT_IN, idsForTestProcess2.get(0), idsForTestProcess2.get(1))
       .count());
   }
-  
+
   public void testProcessDefinitionNotIn() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(6, executionService.createProcessInstanceQuery()
       .processDefinitionId(QueryOperator.NOT_IN, "testProcess1-1", "testProcess2")
       .count());
   }
-  
+
   public void testProcessInstanceKeyNotIn() {
     startTestProcesses(4, 6);
-    
+
     assertEquals(10, executionService.createProcessInstanceQuery().count());
-    
+
     assertEquals(8, executionService.createProcessInstanceQuery()
       .processInstanceKey(QueryOperator.NOT_IN, "testProcess1-0", "testProcess1-1")
       .count());
   }
-  
+
   public void testQueryByProcessInstanceIdWithInitiator() {
     deployJpdlXmlString(TEST_PROCESS_1);
     deployJpdlXmlString(TEST_PROCESS_2);
-    
+
     processEngine.setAuthenticatedUserId("mike");
     ProcessInstance pi = executionService.startProcessInstanceByKey(TEST_PROCESS_1_KEY);
-    
+
     processEngine.setAuthenticatedUserId("alex");
     ProcessInstance pi2 = executionService.startProcessInstanceByKey(TEST_PROCESS_2_KEY);
-    
+
     assertEquals(2, executionService.createProcessInstanceQuery().initiator(QueryOperator.LIKE, "%e%").count());
-    
+
     assertNotNull(pi.getInitiator());
     assertEquals("mike", pi.getInitiator());
-    
+
     assertNotNull(pi2.getInitiator());
     assertEquals("alex", pi2.getInitiator());
-    
+
     HistoryProcessInstance historypi = historyService.createHistoryProcessInstanceQuery().processInstanceId(pi.getId()).uniqueResult();
     assertNotNull(historypi.getInitiator());
     assertEquals("mike", historypi.getInitiator());
-    
+
     historypi = historyService.createHistoryProcessInstanceQuery().processInstanceId(pi2.getId()).uniqueResult();
     assertNotNull(historypi.getInitiator());
     assertEquals("alex", historypi.getInitiator());
-    
+
     historypi = historyService.createHistoryProcessInstanceQuery().initiator("mike").uniqueResult();
     assertNotNull(historypi);
-    
+
     assertEquals(2, historyService.createHistoryProcessInstanceQuery().initiator(QueryOperator.LIKE, "%e%").count());
   }
-  
+
   /**
    * Returns a map containing a processKey - processInstanceId mapping.
    * eg. TEST_PROCESS_1 - {"1", "5", "7", "8"}
-   * 
+   *
    * Process instance will also have a business key of the form 'processDefKey-nr', where
    * nr is from 0 to the given nr of required processes.
    */
@@ -356,22 +362,22 @@
     if (nrOfTestProcess2 > 0) {
       deployJpdlXmlString(TEST_PROCESS_2);
     }
-    
+
     Map<String, ArrayList<String>> result = new HashMap<String, ArrayList<String>>();
     result.put(TEST_PROCESS_1_KEY, new ArrayList<String>());
     result.put(TEST_PROCESS_2_KEY, new ArrayList<String>());
-    
+
     for (int i = 0; i < nrOfTestProcess1; i++) {
       ProcessInstance pi = executionService.startProcessInstanceByKey(TEST_PROCESS_1_KEY, TEST_PROCESS_1_KEY + "-" + i);
       result.get(TEST_PROCESS_1_KEY).add(pi.getId());
     }
-    
 
+
     for (int i = 0; i < nrOfTestProcess2; i++) {
       ProcessInstance pi = executionService.startProcessInstanceByKey(TEST_PROCESS_2_KEY, TEST_PROCESS_2_KEY + "-" + i);
       result.get(TEST_PROCESS_2_KEY).add(pi.getId());
     }
-   
+
     return result;
   }
 

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/TaskQueryTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/TaskQueryTest.java	2010-10-07 09:40:50 UTC (rev 6747)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/query/TaskQueryTest.java	2010-10-08 09:25:57 UTC (rev 6748)
@@ -31,6 +31,7 @@
 
 import org.jbpm.api.QueryOperator;
 import org.jbpm.api.TaskQuery;
+import org.jbpm.api.task.Participation;
 import org.jbpm.api.task.Task;
 import org.jbpm.test.JbpmTestCase;
 import org.jbpm.test.assertion.QueryAssertions;
@@ -39,32 +40,25 @@
  * @author Tom Baeyens
  */
 public class TaskQueryTest extends JbpmTestCase {
-	
+
   public void testPropertyNames() {
-  	Task task = taskService.newTask();
-  	task.setName("write task query test");
-  	task.setAssignee("koen");
-  	task.setPriority(Integer.MAX_VALUE);
-  	task.setDescription("make sure the test fails if property names are incorrect");
-  	task.setDuedate(new Date());
-  	String taskId = taskService.saveTask(task);
-	
+    Task task = taskService.newTask();
+    task.setName("write task query test");
+    task.setAssignee("koen");
+    task.setPriority(Integer.MAX_VALUE);
+    task.setDescription("make sure the test fails if property names are incorrect");
+    task.setDuedate(new Date());
+    String taskId = taskService.saveTask(task);
+
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_ASSIGNEE);
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_CREATEDATE);
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_DUEDATE);
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_NAME);
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_PRIORITY);
     checkProperty(taskService.createTaskQuery(), task, TaskQuery.PROPERTY_PROGRESS);
-    
+
     taskService.deleteTaskCascade(taskId);
   }
-  
-  private void checkProperty(TaskQuery taskQuery, Task task, String propertyName) {
-  	List<Task> taskList = taskQuery.orderAsc(propertyName).list();
-  	assertNotNull(taskList);
-  	assertContainsTask(taskList, task.getName());
-  	assertEquals(1, taskList.size());
-  }
 
   public void testSimplestTaskQuery() {
     List<Task> tasks = createTestTasks();
@@ -73,99 +67,199 @@
       .createTaskQuery()
       .list();
     assertNotNull(taskList);
-    
+
     assertContainsTask(taskList, "do laundry");
     assertContainsTask(taskList, "change diaper");
     assertContainsTask(taskList, "start new business");
     assertContainsTask(taskList, "find venture capital");
 
     assertEquals(4, taskList.size());
-    
+
     deleteTasks(tasks);
   }
 
+  public void testUnassign() {
+    Task task = taskService.newTask();
+    task.setName("unassign");
+    taskService.saveTask(task);
+
+    List<Task> taskList = taskService
+      .createTaskQuery()
+      .unassigned()
+      .list();
+
+    assertEquals(1, taskList.size());
+
+    taskService.deleteTaskCascade(task.getId());
+  }
+
   public void testOrderByName() {
-    testOrderBy(TaskQuery.PROPERTY_NAME, 
+    testOrderBy(TaskQuery.PROPERTY_NAME,
             "change diaper", "do laundry", "find venture capital", "start new business");
   }
-  
+
   public void testOrderByAssignee() {
     testOrderBy(TaskQuery.PROPERTY_ASSIGNEE, "Alex", "Joram", "Koen", "Tom");
   }
-  
+
   public void testOrderByCreateTime() {
     testOrderByResultsInNaturalOrdening(TaskQuery.PROPERTY_CREATEDATE, 4);
   }
-  
+
   public void testOrderByDueDate() {
     testOrderByResultsInNaturalOrdening(TaskQuery.PROPERTY_DUEDATE, 4);
   }
-  
+
   public void testOrderByPriority() {
     testOrderByResultsInNaturalOrdening(TaskQuery.PROPERTY_PRIORITY, 4);
   }
-  
+
   public void testOrderByProgress() {
     testOrderBy(TaskQuery.PROPERTY_PROGRESS, 2, 15, 75, 99);
   }
-  
+
   public void testCount() {
     List<Task> tasks = new ArrayList<Task>();
-    
+
     final String assignee = "task1";
     for (int i= 0; i < 30; i++) {
       Task task = taskService.newTask();
-      
+
       // assign half of the tasks
       if ( i % 2 == 0) {
         task.setAssignee(assignee);
       }
-      
+
       taskService.saveTask(task);
       tasks.add(task);
     }
-    
+
     TaskQuery taskQuery = taskService.createTaskQuery();
     assertEquals(30, taskQuery.count());
     assertEquals(15, taskQuery.assignee(assignee).count());
-    
+
     deleteTasks(tasks);
   }
-  
+
   public void testTaskQueryAssigneeLike() {
     List<Task> tasks = createTestTasks();
 
     assertEquals(2, taskService.createTaskQuery()
       .assignee(QueryOperator.LIKE, "%o%m")
       .count());
-    
+
     deleteTasks(tasks);
   }
-  
+
   public void testTaskQueryAssigneeIn() {
     List<Task> tasks = createTestTasks();
 
     assertEquals(2, taskService.createTaskQuery()
       .assignee(QueryOperator.IN, "Koen", "Tom")
       .count());
-    
+
     deleteTasks(tasks);
   }
-  
+
   public void testTaskQueryAssigneeNotIn() {
     List<Task> tasks = createTestTasks();
 
     assertEquals(1, taskService.createTaskQuery()
       .assignee(QueryOperator.NOT_IN, "Koen", "Tom", "Alex")
       .count());
-    
+
     deleteTasks(tasks);
   }
-  
+
+  // ~ ========================================================================
+
+  public void testCandidate() {
+    Task task = taskService.newTask();
+    task.setName("candidate");
+    taskService.saveTask(task);
+    taskService.addTaskParticipatingUser(task.getId(), "Lingo", Participation.CANDIDATE);
+
+    List<Task> taskList = taskService
+      .createTaskQuery()
+      .candidate("Lingo")
+      .orderAsc(TaskQuery.PROPERTY_NAME)
+      .list();
+
+    assertEquals(1, taskList.size());
+
+    taskService.deleteTaskCascade(task.getId());
+  }
+
+  public void testCandidateAndUnassign() {
+    Task task = taskService.newTask();
+    task.setName("unassign");
+    taskService.saveTask(task);
+    taskService.addTaskParticipatingUser(task.getId(), "Lingo", Participation.CANDIDATE);
+
+    List<Task> taskList = taskService
+      .createTaskQuery()
+      .candidate("Lingo")
+      .unassigned()
+      .list();
+
+    assertEquals(1, taskList.size());
+
+    taskService.deleteTaskCascade(task.getId());
+  }
+
+  public void testUniqueCandidateNoRecord() {
+
+    Task task = taskService
+      .createTaskQuery()
+      .candidate("Lingo")
+      .orderAsc(TaskQuery.PROPERTY_NAME)
+      .uniqueResult();
+
+    assertNull(task);
+  }
+
+  public void testCandidateGroup() {
+    Task task1 = taskService.newTask();
+    task1.setName("candidate");
+    taskService.saveTask(task1);
+    taskService.addTaskParticipatingGroup(task1.getId(), "dev", Participation.CANDIDATE);
+
+    Task task2 = taskService.newTask();
+    taskService.saveTask(task2);
+    taskService.addTaskParticipatingGroup(task2.getId(), "none-exist-group", Participation.CANDIDATE);
+
+    identityService.createUser("Lingo", "Lingo", "XuHuiSheng");
+    identityService.createGroup("dev");
+    identityService.createMembership("Lingo", "dev");
+
+    Task task = taskService
+      .createTaskQuery()
+      .candidate("Lingo")
+      .orderAsc(TaskQuery.PROPERTY_NAME)
+      .uniqueResult();
+
+    assertEquals("candidate", task.getName());
+
+    taskService.deleteTaskCascade(task1.getId());
+    taskService.deleteTaskCascade(task2.getId());
+
+    identityService.deleteUser("Lingo");
+    identityService.deleteGroup("dev");
+  }
+
+  // ~ ========================================================================
+
   /* -------------------------------------------------------------------
    * HELPER METHODS
    * ------------------------------------------------------------------- */
-  
+
+  private void checkProperty(TaskQuery taskQuery, Task task, String propertyName) {
+    List<Task> taskList = taskQuery.orderAsc(propertyName).list();
+    assertNotNull(taskList);
+    assertContainsTask(taskList, task.getName());
+    assertEquals(1, taskList.size());
+  }
+
   private List<Task> createTestTasks() {
     List<Task> result = new ArrayList<Task>();
 
@@ -182,7 +276,7 @@
     task2.setPriority(1);
     task2.setDuedate(stringToDate("28/06/1989"));
     task2.setProgress(2);
-    
+
     Task task3 = taskService.newTask();
     task3.setName("start new business");
     task3.setAssignee("Joram");
@@ -195,18 +289,18 @@
     task4.setPriority(7);
     task4.setDuedate(stringToDate("09/09/2009"));
     task4.setProgress(99);
-    
+
     for (Task t : new Task[] {task1, task2, task3, task4}) {
       taskService.saveTask(t);
       result.add(t);
     }
-    
+
     return result;
   }
-  
+
   private void testOrderBy(String property, Object... expectedValues) {
     List<Task> tasks = createTestTasks();
-    
+
     List<Task> taskListAsc = taskService.createTaskQuery().orderAsc(property).list();
     List<Task> taskListDesc = taskService.createTaskQuery().orderDesc(property).list();
 
@@ -219,18 +313,18 @@
     List<Task> tasks = createTestTasks();
     List<Task> taskListAsc = taskService.createTaskQuery().orderAsc(property).list();
     List<Task> taskListDesc = taskService.createTaskQuery().orderDesc(property).list();
-    
+
     QueryAssertions.assertOrderIsNatural(Task.class, property, taskListAsc, taskListDesc, expectedNrOfResults);
-    
+
     deleteTasks(tasks);
   }
-  
+
   private void deleteTasks(List<Task> tasks) {
     for (Task t : tasks) {
       taskService.deleteTaskCascade(t.getId());
     }
   }
-  
+
   private Date stringToDate(String dateString) {
     DateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
     try {
@@ -239,5 +333,5 @@
       throw new AssertionError(e);
     }
   }
-  
+
 }



More information about the jbpm-commits mailing list