### Eclipse Workspace Patch 1.0 #P jbpm4 Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java (revision 6478) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessInstanceQueryImpl.java (working copy) @@ -26,6 +26,7 @@ import org.hibernate.Query; import org.jbpm.api.ProcessInstance; import org.jbpm.api.ProcessInstanceQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.pvm.internal.model.ExecutionImpl; import org.jbpm.pvm.internal.util.CollectionUtil; @@ -132,5 +133,9 @@ this.suspended = false; return this; } - + public String operand(String parameter, QueryOperand operand) { + parameterOperands.put(parameter, operand); + + return parameter; + } } Index: modules/api/src/main/java/org/jbpm/api/ProcessDefinitionQuery.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/ProcessDefinitionQuery.java (revision 6403) +++ modules/api/src/main/java/org/jbpm/api/ProcessDefinitionQuery.java (working copy) @@ -79,4 +79,7 @@ /** execute a count(*) query and returns number of results */ long count(); + + /** allows to specify query operand for given parameter value*/ + String operand(String parameter, QueryOperand operand); } Index: modules/api/src/main/java/org/jbpm/api/QueryOperand.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/QueryOperand.java (revision 0) +++ modules/api/src/main/java/org/jbpm/api/QueryOperand.java (revision 0) @@ -0,0 +1,26 @@ +package org.jbpm.api; + + +public enum QueryOperand { + + EQUALS(0, "="), + LIKE(1, "like"), + IN(2, "in"), + NOT_IN(3, "not in"); + + @SuppressWarnings("unused") + private int id; + private String value; + + QueryOperand(int id, String value) { + this.id = id; + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + +} Property changes on: modules\api\src\main\java\org\jbpm\api\QueryOperand.java ___________________________________________________________________ Added: svn:keywords + Id Revision Added: svn:eol-style + LF Index: modules/api/src/main/java/org/jbpm/api/ProcessInstanceQuery.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/ProcessInstanceQuery.java (revision 6403) +++ modules/api/src/main/java/org/jbpm/api/ProcessInstanceQuery.java (working copy) @@ -69,4 +69,7 @@ /** execute a count(*) query and returns number of results */ long count(); + + /** allows to specify query operand for given parameter value*/ + String operand(String parameter, QueryOperand operand); } Index: modules/test-db/src/test/java/org/jbpm/test/query/JobQueryTest.java =================================================================== --- modules/test-db/src/test/java/org/jbpm/test/query/JobQueryTest.java (revision 6403) +++ modules/test-db/src/test/java/org/jbpm/test/query/JobQueryTest.java (working copy) @@ -26,6 +26,7 @@ import java.util.List; import org.jbpm.api.JobQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.api.job.Job; import org.jbpm.test.JbpmTestCase; import org.jbpm.test.assertion.QueryAssertions; @@ -143,6 +144,38 @@ } + public void testProcessIdLike() { + startTestProcessInstances(6); + + JobQuery query = managementService.createJobQuery(); + assertEquals(6, query.processInstanceId(query.operand("TimerQueryTest%", QueryOperand.LIKE)).count()); + + } + + public void testProcessIdEquals() { + List procInstIds = startTestProcessInstances(6); + + JobQuery query = managementService.createJobQuery(); + assertEquals(1, query.processInstanceId(query.operand(procInstIds.get(0), QueryOperand.EQUALS)).count()); + + } + + public void testProcessIdIn() { + List procInstIds = startTestProcessInstances(6); + + JobQuery query = managementService.createJobQuery(); + assertEquals(2, query.processInstanceId(query.operand(""+procInstIds.get(0)+","+procInstIds.get(1)+"", QueryOperand.IN)).count()); + + } + + public void testProcessIdNotIn() { + List procInstIds = startTestProcessInstances(6); + + JobQuery query = managementService.createJobQuery(); + assertEquals(4, query.processInstanceId(query.operand(""+procInstIds.get(0)+","+procInstIds.get(1)+"", QueryOperand.NOT_IN)).count()); + + } + private List startTestProcessInstances(int nrOfInstances) { deployJpdlXmlString( "" + Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java (revision 6426) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/AbstractQuery.java (working copy) @@ -22,12 +22,15 @@ package org.jbpm.pvm.internal.query; import java.io.ObjectStreamException; +import java.lang.reflect.Array; +import java.util.HashMap; 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.QueryOperand; import org.jbpm.api.cmd.Command; import org.jbpm.api.cmd.Environment; import org.jbpm.pvm.internal.cmd.CommandService; @@ -47,6 +50,8 @@ protected boolean count; protected boolean uniqueResult; + protected Map parameterOperands = new HashMap(); + protected abstract void applyParameters(Query query); public abstract String hql(); @@ -155,7 +160,66 @@ this.commandService = null; return this; } + + protected QueryOperand getOperand(String param) { + if (parameterOperands.containsKey(param)) { + return parameterOperands.get(param); + } + return QueryOperand.EQUALS; + } + + protected boolean isListOperand(String param) { + QueryOperand operand = getOperand(param); + + if (operand == QueryOperand.IN || operand == QueryOperand.NOT_IN) { + return true; + } else { + return false; + } + } + + /** + * Transforms given string (parameter) to an array of given type (clazz). + * parameter will be split using separator ',' (comma). + * Array will be populated based on split string by creating new instance of class clazz + * using its constructor that accepts String argument. + * All exceptions will be silently skipped. + */ + @SuppressWarnings("unchecked") + protected T[] transformToArray(String parameter, T clazz) { + String[] idsStr = parameter.split(","); + if (clazz instanceof String) { + return (T[]) idsStr; + } + T[] ids = (T[]) Array.newInstance( (Class)clazz, idsStr.length); + + for (int i = 0; i < idsStr.length; i++) { + try { + ids[i] = (T) ((Class)clazz).getConstructor(String.class).newInstance(idsStr[i]); + } catch (Exception e) { + } + } + return ids; + } + + protected void appendWhereClauseWithOperand(String parameter, String where, String namedParam, StringBuilder hql) { + QueryOperand operand = getOperand(parameter); + if (isListOperand(parameter)) { + appendWhereClause(where + " " + operand + " (:" + namedParam + ") ", hql); + } else { + appendWhereClause(where + " " + operand + " :" + namedParam + " ", hql); + } + } + + protected void applyParameterWithOperand(String parameter, String namedParam, Class clazz, Query query) { + if (isListOperand(parameter)) { + query.setParameterList(namedParam, transformToArray(parameter, clazz)); + } else { + query.setString(namedParam, parameter); + } + } + public void setCommandService(CommandService commandService) { this.commandService = commandService; } Index: modules/api/src/main/java/org/jbpm/api/JobQuery.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/JobQuery.java (revision 6478) +++ modules/api/src/main/java/org/jbpm/api/JobQuery.java (working copy) @@ -49,6 +49,9 @@ /** only select jobs related to the given process instance */ JobQuery processInstanceId(String processInstanceId); + + /** allows to specify query operand for given parameter value*/ + String operand(String parameter, QueryOperand operand); /** only select jobs that were rolled back due to an exception */ JobQuery exception(boolean hasException); Index: modules/api/src/main/java/org/jbpm/api/DeploymentQuery.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/DeploymentQuery.java (revision 6403) +++ modules/api/src/main/java/org/jbpm/api/DeploymentQuery.java (working copy) @@ -60,4 +60,7 @@ /** execute a count(*) query and returns number of results */ long count(); + + /** allows to specify query operand for given parameter value*/ + String operand(String parameter, QueryOperand operand); } Index: modules/api/src/main/java/org/jbpm/api/TaskQuery.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/TaskQuery.java (revision 6478) +++ modules/api/src/main/java/org/jbpm/api/TaskQuery.java (working copy) @@ -94,4 +94,7 @@ /** execute the query and obtain the unique {@link Task} */ Task uniqueResult(); + + /** allows to specify query operand for given parameter value*/ + String operand(String parameter, QueryOperand operand); } Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java (revision 6555) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/TaskQueryImpl.java (working copy) @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.jbpm.api.JbpmException; +import org.jbpm.api.QueryOperand; import org.jbpm.api.TaskQuery; import org.jbpm.api.identity.Group; import org.jbpm.api.task.Task; @@ -296,4 +297,10 @@ public Task uniqueResult() { return (Task) untypedUniqueResult(); } + + public String operand(String parameter, QueryOperand operand) { + parameterOperands.put(parameter, operand); + + return parameter; + } } Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java (revision 6478) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/JobQueryImpl.java (working copy) @@ -25,6 +25,7 @@ import org.hibernate.Query; import org.jbpm.api.JobQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.api.job.Job; import org.jbpm.pvm.internal.job.JobImpl; import org.jbpm.pvm.internal.job.MessageImpl; @@ -43,6 +44,8 @@ protected boolean timersOnly = false; protected String processInstanceId = null; protected Boolean exception; + + public String hql() { StringBuilder hql = new StringBuilder(); @@ -65,8 +68,9 @@ hql.append(" j "); if (processInstanceId!=null) { - appendWhereClause("j.processInstance.id = '"+processInstanceId+"' ", hql); - } + appendWhereClauseWithOperand(processInstanceId, "j.processInstance.id", "processInstanceId", hql); + } + if (exception!=null) { if (exception) { @@ -82,6 +86,9 @@ } protected void applyParameters(Query query) { + if (processInstanceId != null) { + applyParameterWithOperand(processInstanceId, "processInstanceId", String.class, query); + } } public List list() { @@ -126,4 +133,10 @@ this.processInstanceId = processInstanceId; return this; } + + public String operand(String parameter, QueryOperand operand) { + parameterOperands.put(parameter, operand); + + return parameter; + } } Index: modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java =================================================================== --- modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java (revision 6403) +++ modules/test-db/src/test/java/org/jbpm/test/query/DeploymentQueryTest.java (working copy) @@ -28,6 +28,7 @@ import org.jbpm.api.Deployment; import org.jbpm.api.DeploymentQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.test.JbpmTestCase; import org.jbpm.test.assertion.QueryAssertions; @@ -113,6 +114,50 @@ deleteCascade(deploymentIds); } + public void testEquals() { + List deploymentIds = deployTestProcesses(); + + DeploymentQuery query = repositoryService.createDeploymentQuery(); + + assertEquals(1, query.deploymentId(query.operand(deploymentIds.get(0), QueryOperand.EQUALS)).count()); + + + deleteCascade(deploymentIds); + } + + public void testLike() { + List deploymentIds = deployTestProcesses(); + + DeploymentQuery query = repositoryService.createDeploymentQuery(); + + assertEquals(1, query.deploymentId(query.operand(deploymentIds.get(0), QueryOperand.LIKE)).count()); + + + deleteCascade(deploymentIds); + } + + public void testIn() { + List deploymentIds = deployTestProcesses(); + + DeploymentQuery query = repositoryService.createDeploymentQuery(); + + assertEquals(2, query.deploymentId(query.operand(deploymentIds.get(0) + ","+deploymentIds.get(1), QueryOperand.IN)).count()); + + + deleteCascade(deploymentIds); + } + + public void testNotIn() { + List deploymentIds = deployTestProcesses(); + + DeploymentQuery query = repositoryService.createDeploymentQuery(); + + assertEquals(2, query.deploymentId(query.operand(deploymentIds.get(0), QueryOperand.NOT_IN)).count()); + + + deleteCascade(deploymentIds); + } + /* -------------- * HELPER METHODS * -------------- */ Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java (revision 6479) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/ProcessDefinitionQueryImpl.java (working copy) @@ -31,6 +31,7 @@ import org.jbpm.api.Deployment; import org.jbpm.api.ProcessDefinition; import org.jbpm.api.ProcessDefinitionQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.pvm.internal.env.EnvironmentImpl; import org.jbpm.pvm.internal.model.ProcessDefinitionImpl; import org.jbpm.pvm.internal.repository.DeploymentImpl; @@ -126,24 +127,25 @@ appendWhereClause("versionProperty.deployment = deployment ", hql); if (id!=null) { - appendWhereClause("idProperty.stringValue = '"+id+"'", hql); + appendWhereClauseWithOperand(id, "idProperty.stringValue", "id", hql); } - if (nameLike!=null) { - appendWhereClause("idProperty.objectName like '"+nameLike+"' ", hql); - } - if (name!=null) { - appendWhereClause("idProperty.objectName = '"+name+"' ", hql); + appendWhereClauseWithOperand(name, "idProperty.objectName", "name", hql); } if (key!=null) { - appendWhereClause("keyProperty.stringValue = '"+key+"' ", hql); + appendWhereClauseWithOperand(key, "keyProperty.stringValue", "key", hql); } if (deploymentId!=null) { - appendWhereClause("idProperty.deployment.dbid = "+deploymentId+" ", hql); + appendWhereClauseWithOperand(deploymentId, "idProperty.deployment.dbid", "deploymentId", hql); } + + // @deprecated, should be used with operand + if (nameLike!=null) { + appendWhereClause("idProperty.objectName like '"+nameLike+"' ", hql); + } appendOrderByClause(hql); @@ -151,6 +153,22 @@ } protected void applyParameters(Query query) { + if (id != null) { + applyParameterWithOperand(id, "id", String.class, query); + } + + if (name != null) { + applyParameterWithOperand(name, "name", String.class, query); + } + + if (key != null) { + applyParameterWithOperand(key, "key", String.class, query); + } + + if (deploymentId != null) { + applyParameterWithOperand(deploymentId, "deploymentId", Long.class, query); + } + } public List list() { @@ -215,4 +233,10 @@ this.page = new Page(firstResult, maxResults); return this; } + + public String operand(String parameter, QueryOperand operand) { + parameterOperands.put(parameter, operand); + + return parameter; + } } Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java (revision 6478) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/query/DeploymentQueryImpl.java (working copy) @@ -26,6 +26,7 @@ import org.hibernate.Query; import org.jbpm.api.Deployment; import org.jbpm.api.DeploymentQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.pvm.internal.repository.DeploymentImpl; import org.jbpm.pvm.internal.util.CollectionUtil; @@ -53,7 +54,7 @@ hql.append(" as d "); if (deploymentId!=null) { - appendWhereClause("d.dbid = "+deploymentId+" ", hql); + appendWhereClauseWithOperand(deploymentId, "d.dbid", "deploymentId", hql); } if (suspended!=null) { @@ -70,6 +71,10 @@ } protected void applyParameters(Query query) { + + if (deploymentId != null) { + applyParameterWithOperand(deploymentId, "deploymentId", Long.class, query); + } } public DeploymentQuery deploymentId(String deploymentId) { @@ -109,4 +114,10 @@ public Deployment uniqueResult() { return (Deployment) untypedUniqueResult(); } + + public String operand(String parameter, QueryOperand operand) { + parameterOperands.put(parameter, operand); + + return parameter; + } } Index: modules/test-db/src/test/java/org/jbpm/test/query/ProcessDefinitionQueryTest.java =================================================================== --- modules/test-db/src/test/java/org/jbpm/test/query/ProcessDefinitionQueryTest.java (revision 6403) +++ modules/test-db/src/test/java/org/jbpm/test/query/ProcessDefinitionQueryTest.java (working copy) @@ -25,6 +25,7 @@ import org.jbpm.api.ProcessDefinition; import org.jbpm.api.ProcessDefinitionQuery; +import org.jbpm.api.QueryOperand; import org.jbpm.test.JbpmTestCase; @@ -135,4 +136,128 @@ assertEquals("make_friends-3", processDefinitions.get(2).getId()); assertEquals("make_print-1", processDefinitions.get(3).getId()); } + + public void testQueryProcessDefinitionsLike() { + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); + List processDefinitions = + query.processDefinitionName(query.operand("%make%", QueryOperand.LIKE)) + .orderAsc(ProcessDefinitionQuery.PROPERTY_NAME) + .list(); + + assertEquals("fix coffeemaker", processDefinitions.get(0).getName()); + assertEquals("make friends", processDefinitions.get(1).getName()); + assertEquals("make print", processDefinitions.get(2).getName()); + } + + public void testQueryProcessDefinitionsIn() { + String dbId1 = deployJpdlXmlString( + "" + + " " + + "" + ); + + String dbId2 = deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); + List processDefinitions = + query.deploymentId(query.operand(dbId1+","+dbId2, QueryOperand.IN)) + .orderAsc(ProcessDefinitionQuery.PROPERTY_NAME) + .list(); + + assertEquals(2, processDefinitions.size()); + + } + + public void testQueryProcessDefinitionsNotIn() { + String dbId1 = deployJpdlXmlString( + "" + + " " + + "" + ); + + String dbId2 = deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + deployJpdlXmlString( + "" + + " " + + "" + ); + + ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); + List processDefinitions = + query.deploymentId(query.operand(dbId1+","+dbId2, QueryOperand.NOT_IN)) + .orderAsc(ProcessDefinitionQuery.PROPERTY_NAME) + .list(); + + assertEquals(3, processDefinitions.size()); + + } }