diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.java index a62690b60a5..a08ab858d40 100755 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.java @@ -24,6 +24,7 @@ import java.util.List; import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.FlowableIllegalArgumentException; import org.flowable.common.engine.api.scope.ScopeTypes; import org.flowable.common.engine.impl.interceptor.Command; import org.flowable.common.engine.impl.interceptor.CommandContext; @@ -198,6 +199,102 @@ public void testQueryByElementId() { } + @Test + @Deployment(resources = "org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.bpmn20.xml") + public void testQueryByElementIds() { + ProcessInstance processInstance1 = runtimeService.startProcessInstanceByKey("externalWorkerJobQueryTest"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("externalWorkerJobQueryTest"); + + // both element ids -> all four jobs (two per instance) + assertThat(managementService.createExternalWorkerJobQuery() + .elementIds(List.of("externalOrder", "externalCustomer1")).count()).isEqualTo(4); + + // single element id -> one per instance + assertThat(managementService.createExternalWorkerJobQuery() + .elementIds(List.of("externalOrder")).list()) + .extracting(ExternalWorkerJob::getProcessInstanceId) + .containsExactlyInAnyOrder(processInstance1.getId(), processInstance2.getId()); + + assertThat(managementService.createExternalWorkerJobQuery() + .elementIds(List.of("invalid")).count()).isZero(); + + // empty collection is ignored (the filter is not applied) + assertThat(managementService.createExternalWorkerJobQuery() + .elementIds(Collections.emptyList()).count()) + .isEqualTo(managementService.createExternalWorkerJobQuery().count()); + + assertThatThrownBy(() -> managementService.createExternalWorkerJobQuery().elementIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + } + + @Test + @Deployment(resources = "org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.bpmn20.xml") + public void testOrQueryByElementIds() { + ProcessInstance processInstance1 = runtimeService.startProcessInstanceByKey("externalWorkerJobQueryTest"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("externalWorkerJobQueryTest"); + + // AND (processInstanceId) + OR (elementIds): only processInstance1's two jobs + List jobs = managementService.createExternalWorkerJobQuery() + .processInstanceId(processInstance1.getId()) + .or() + .elementIds(List.of("externalOrder", "externalCustomer1")) + .endOr() + .list(); + assertThat(jobs).hasSize(2); + assertThat(jobs).extracting(ExternalWorkerJob::getProcessInstanceId) + .containsOnly(processInstance1.getId()); + + // OR (jobId OR elementIds): orderJob1 by id, plus every "externalCustomer1" job by element + ExternalWorkerJob orderJob1 = managementService.createExternalWorkerJobQuery() + .processInstanceId(processInstance1.getId()) + .elementId("externalOrder") + .singleResult(); + jobs = managementService.createExternalWorkerJobQuery() + .or() + .jobId(orderJob1.getId()) + .elementIds(List.of("externalCustomer1")) + .endOr() + .list(); + assertThat(jobs).extracting(ExternalWorkerJob::getElementId) + .containsExactlyInAnyOrder("externalOrder", "externalCustomer1", "externalCustomer1"); + assertThat(jobs).extracting(ExternalWorkerJob::getProcessInstanceId) + .contains(processInstance1.getId(), processInstance2.getId()); + } + + @Test + public void testQueryByScopeIds() { + // covers the SCOPE_ID_ block of ExternalWorkerJob.xml, which the elementIds tests do not exercise + ExternalWorkerJobEntity job1 = createExternalWorkerJobWithScope("agent", "scope1", "element1"); + ExternalWorkerJobEntity job2 = createExternalWorkerJobWithScope("agent", null, "element2"); + + assertThat(managementService.createExternalWorkerJobQuery().scopeIds(List.of("scope1")).count()).isEqualTo(1); + assertThat(managementService.createExternalWorkerJobQuery().scopeIds(List.of("scope1", "scope2")).count()).isEqualTo(1); + assertThat(managementService.createExternalWorkerJobQuery().scopeIds(List.of("unknown")).count()).isZero(); + + // scopeIds OR elementIds inside an or() + assertThat(managementService.createExternalWorkerJobQuery().or() + .scopeIds(List.of("scope1")) + .elementIds(List.of("element2")) + .endOr().list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId()); + + // empty collection is ignored (the filter is not applied) + assertThat(managementService.createExternalWorkerJobQuery().scopeIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createExternalWorkerJobQuery().count()); + + assertThatThrownBy(() -> managementService.createExternalWorkerJobQuery().scopeIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + + managementService.executeCommand(commandContext -> { + ExternalWorkerJobEntityManager externalWorkerJobEntityManager = CommandContextUtil.getProcessEngineConfiguration(commandContext) + .getJobServiceConfiguration().getExternalWorkerJobEntityManager(); + externalWorkerJobEntityManager.delete(job1.getId()); + externalWorkerJobEntityManager.delete(job2.getId()); + return null; + }); + } + @Test @Deployment(resources = "org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.bpmn20.xml") public void testQueryByElementName() { @@ -700,6 +797,20 @@ public Void execute(CommandContext commandContext) { }); } + private ExternalWorkerJobEntity createExternalWorkerJobWithScope(String scopeType, String scopeId, String elementId) { + return managementService.executeCommand(commandContext -> { + JobService jobService = CommandContextUtil.getJobService(commandContext); + ExternalWorkerJobEntity jobEntity = jobService.createExternalWorkerJob(); + jobEntity.setJobType(Job.JOB_TYPE_EXTERNAL_WORKER); + jobEntity.setScopeType(scopeType); + jobEntity.setScopeId(scopeId); + jobEntity.setElementId(elementId); + jobService.insertExternalWorkerJob(jobEntity); + assertThat(jobEntity.getId()).isNotNull(); + return jobEntity; + }); + } + @Test @Deployment(resources = "org/flowable/engine/test/api/mgmt/ExternalWorkerJobQueryTest.bpmn20.xml") public void testOrQuery() { diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/JobQueryTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/JobQueryTest.java index 3dfc949f317..f83d72d3666 100755 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/JobQueryTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/mgmt/JobQueryTest.java @@ -61,6 +61,8 @@ import org.flowable.job.service.impl.persistence.entity.JobEntity; import org.flowable.job.service.impl.persistence.entity.SuspendedJobEntity; import org.flowable.job.service.impl.persistence.entity.SuspendedJobEntityManager; +import org.flowable.job.service.impl.persistence.entity.TimerJobEntity; +import org.flowable.job.service.impl.persistence.entity.TimerJobEntityManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -342,6 +344,183 @@ public void testQueryByHandlerTypes() { managementService.deleteJob(managementService.createJobQuery().handlerType("Type2").singleResult().getId()); } + @Test + public void testQueryByScopeIdsAndElementIds() { + // scope1/element1 = content agent job, scope2/element2 = tree agent job, null scope = classify job (elementId only) + JobEntity job1 = createJobWithScope("agent", "scope1", "element1"); + JobEntity job2 = createJobWithScope("agent", "scope2", "element2"); + JobEntity classifyJob = createJobWithScope("agent", null, "element3"); + + // scopeIds + assertThat(managementService.createJobQuery().scopeIds(List.of("scope1", "scope2")).count()).isEqualTo(2); + assertThat(managementService.createJobQuery().scopeIds(List.of("scope1")).count()).isEqualTo(1); + assertThat(managementService.createJobQuery().scopeIds(List.of("unknown")).count()).isZero(); + + // elementIds + assertThat(managementService.createJobQuery().elementIds(List.of("element1", "element2", "element3")).count()).isEqualTo(3); + assertThat(managementService.createJobQuery().elementIds(List.of("element1")).count()).isEqualTo(1); + assertThat(managementService.createJobQuery().elementIds(List.of("unknown")).count()).isZero(); + + // scopeIds OR elementIds: job1 matches by scope, job2 + classifyJob match by element + assertThat(managementService.createJobQuery().or() + .scopeIds(List.of("scope1")) + .elementIds(List.of("element2", "element3")) + .endOr().list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId(), classifyJob.getId()); + + // the AgentJobResolver shape: scopeType = agent AND (scopeId IN ... OR elementId IN ...) + assertThat(managementService.createJobQuery() + .scopeType("agent") + .or() + .scopeIds(List.of("scope1", "scope2")) + .elementIds(List.of("element3")) + .endOr() + .list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId(), classifyJob.getId()); + + // that same AND narrows the scope type: no jobs for a different scope type + assertThat(managementService.createJobQuery() + .scopeType("other") + .or() + .scopeIds(List.of("scope1", "scope2")) + .elementIds(List.of("element3")) + .endOr() + .count()).isZero(); + + // empty collections are ignored (the filter is not applied) + assertThat(managementService.createJobQuery().scopeIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createJobQuery().count()); + assertThat(managementService.createJobQuery().elementIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createJobQuery().count()); + + // null throws + assertThatThrownBy(() -> managementService.createJobQuery().scopeIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + assertThatThrownBy(() -> managementService.createJobQuery().elementIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + + managementService.deleteJob(job1.getId()); + managementService.deleteJob(job2.getId()); + managementService.deleteJob(classifyJob.getId()); + } + + @Test + public void testTimerQueryByElementIds() { + TimerJobQuery query = managementService.createTimerJobQuery().elementIds(List.of("escalationTimer", "unknown")); + verifyQueryResults(query, 3); + + query = managementService.createTimerJobQuery().elementIds(List.of("unknown")); + verifyQueryResults(query, 0); + + // empty collection is ignored (the filter is not applied) + query = managementService.createTimerJobQuery().elementIds(new ArrayList<>()); + verifyQueryResults(query, 3); + + assertThatThrownBy(() -> managementService.createTimerJobQuery().elementIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + } + + @Test + public void testTimerJobQueryByScopeIds() { + // covers the SCOPE_ID_ block of TimerJob.xml, which the elementIds test does not exercise + TimerJobEntity job1 = createTimerJobWithScope("agent", "scope1", "element1"); + TimerJobEntity job2 = createTimerJobWithScope("agent", null, "element2"); + + assertThat(managementService.createTimerJobQuery().scopeIds(List.of("scope1")).count()).isEqualTo(1); + assertThat(managementService.createTimerJobQuery().scopeIds(List.of("scope1", "scope2")).count()).isEqualTo(1); + assertThat(managementService.createTimerJobQuery().scopeIds(List.of("unknown")).count()).isZero(); + + // scopeIds OR elementIds inside an or() + assertThat(managementService.createTimerJobQuery().or() + .scopeIds(List.of("scope1")) + .elementIds(List.of("element2")) + .endOr().list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId()); + + // empty collection is ignored (the filter is not applied) + assertThat(managementService.createTimerJobQuery().scopeIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createTimerJobQuery().count()); + + assertThatThrownBy(() -> managementService.createTimerJobQuery().scopeIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + + managementService.executeCommand(commandContext -> { + JobServiceConfiguration jobServiceConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext).getJobServiceConfiguration(); + TimerJobEntityManager timerJobEntityManager = jobServiceConfiguration.getTimerJobEntityManager(); + timerJobEntityManager.delete(job1.getId()); + timerJobEntityManager.delete(job2.getId()); + return null; + }); + } + + @Test + public void testSuspendedJobQueryByScopeIdsAndElementIds() { + SuspendedJobEntity job1 = createSuspendedJobWithScope("agent", "scope1", "element1"); + SuspendedJobEntity job2 = createSuspendedJobWithScope("agent", null, "element2"); + + assertThat(managementService.createSuspendedJobQuery().scopeIds(List.of("scope1")).count()).isEqualTo(1); + assertThat(managementService.createSuspendedJobQuery().elementIds(List.of("element1", "element2")).count()).isEqualTo(2); + assertThat(managementService.createSuspendedJobQuery().scopeIds(List.of("unknown")).count()).isZero(); + + // scopeIds OR elementIds inside an or() + assertThat(managementService.createSuspendedJobQuery().or() + .scopeIds(List.of("scope1")) + .elementIds(List.of("element2")) + .endOr().list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId()); + + // empty collections are ignored + assertThat(managementService.createSuspendedJobQuery().scopeIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createSuspendedJobQuery().count()); + + assertThatThrownBy(() -> managementService.createSuspendedJobQuery().scopeIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + assertThatThrownBy(() -> managementService.createSuspendedJobQuery().elementIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + + managementService.executeCommand(commandContext -> { + JobServiceConfiguration jobServiceConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext).getJobServiceConfiguration(); + SuspendedJobEntityManager suspendedJobEntityManager = jobServiceConfiguration.getSuspendedJobEntityManager(); + suspendedJobEntityManager.delete(job1.getId()); + suspendedJobEntityManager.delete(job2.getId()); + return null; + }); + } + + @Test + public void testDeadLetterJobQueryByScopeIdsAndElementIds() { + DeadLetterJobEntity job1 = createDeadLetterJobWithScope("agent", "scope1", "element1"); + DeadLetterJobEntity job2 = createDeadLetterJobWithScope("agent", null, "element2"); + + assertThat(managementService.createDeadLetterJobQuery().scopeIds(List.of("scope1")).count()).isEqualTo(1); + assertThat(managementService.createDeadLetterJobQuery().elementIds(List.of("element1", "element2")).count()).isEqualTo(2); + assertThat(managementService.createDeadLetterJobQuery().scopeIds(List.of("unknown")).count()).isZero(); + + // scopeIds OR elementIds inside an or() + assertThat(managementService.createDeadLetterJobQuery().or() + .scopeIds(List.of("scope1")) + .elementIds(List.of("element2")) + .endOr().list()) + .extracting(Job::getId) + .containsExactlyInAnyOrder(job1.getId(), job2.getId()); + + // empty collections are ignored + assertThat(managementService.createDeadLetterJobQuery().elementIds(new ArrayList<>()).count()) + .isEqualTo(managementService.createDeadLetterJobQuery().count()); + + assertThatThrownBy(() -> managementService.createDeadLetterJobQuery().scopeIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + assertThatThrownBy(() -> managementService.createDeadLetterJobQuery().elementIds(null)) + .isExactlyInstanceOf(FlowableIllegalArgumentException.class); + + managementService.deleteDeadLetterJob(job1.getId()); + managementService.deleteDeadLetterJob(job2.getId()); + } + @Test public void testSuspendedJobQueryByType() { String handlerType = "testSuspendedJobType"; @@ -1615,6 +1794,71 @@ public JobEntity execute(CommandContext commandContext) { }); } + private JobEntity createJobWithScope(String scopeType, String scopeId, String elementId) { + CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); + return commandExecutor.execute(new Command<>() { + + @Override + public JobEntity execute(CommandContext commandContext) { + JobService jobService = CommandContextUtil.getJobService(commandContext); + JobEntity result = jobService.createJob(); + result.setJobType(Job.JOB_TYPE_MESSAGE); + result.setRetries(0); + result.setScopeType(scopeType); + result.setScopeId(scopeId); + result.setElementId(elementId); + jobService.insertJob(result); + assertThat(result.getId()).isNotNull(); + return result; + } + }); + } + + private SuspendedJobEntity createSuspendedJobWithScope(String scopeType, String scopeId, String elementId) { + return managementService.executeCommand(commandContext -> { + JobServiceConfiguration jobServiceConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext).getJobServiceConfiguration(); + SuspendedJobEntityManager suspendedJobEntityManager = jobServiceConfiguration.getSuspendedJobEntityManager(); + SuspendedJobEntity job = suspendedJobEntityManager.create(); + job.setJobType(Job.JOB_TYPE_MESSAGE); + job.setScopeType(scopeType); + job.setScopeId(scopeId); + job.setElementId(elementId); + suspendedJobEntityManager.insert(job); + assertThat(job.getId()).isNotNull(); + return job; + }); + } + + private DeadLetterJobEntity createDeadLetterJobWithScope(String scopeType, String scopeId, String elementId) { + return managementService.executeCommand(commandContext -> { + JobServiceConfiguration jobServiceConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext).getJobServiceConfiguration(); + DeadLetterJobEntityManager deadLetterJobEntityManager = jobServiceConfiguration.getDeadLetterJobEntityManager(); + DeadLetterJobEntity job = deadLetterJobEntityManager.create(); + job.setJobType(Job.JOB_TYPE_MESSAGE); + job.setScopeType(scopeType); + job.setScopeId(scopeId); + job.setElementId(elementId); + deadLetterJobEntityManager.insert(job); + assertThat(job.getId()).isNotNull(); + return job; + }); + } + + private TimerJobEntity createTimerJobWithScope(String scopeType, String scopeId, String elementId) { + return managementService.executeCommand(commandContext -> { + JobServiceConfiguration jobServiceConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext).getJobServiceConfiguration(); + TimerJobEntityManager timerJobEntityManager = jobServiceConfiguration.getTimerJobEntityManager(); + TimerJobEntity job = timerJobEntityManager.create(); + job.setJobType(Job.JOB_TYPE_TIMER); + job.setScopeType(scopeType); + job.setScopeId(scopeId); + job.setElementId(elementId); + timerJobEntityManager.insert(job); + assertThat(job.getId()).isNotNull(); + return job; + }); + } + private void createDeadLetterJobWithHandlerType(String handlerType) { CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); commandExecutor.execute(new Command() { diff --git a/modules/flowable-job-service-api/src/main/java/org/flowable/job/api/BaseJobQuery.java b/modules/flowable-job-service-api/src/main/java/org/flowable/job/api/BaseJobQuery.java index 18054b37567..87cc2e3227f 100644 --- a/modules/flowable-job-service-api/src/main/java/org/flowable/job/api/BaseJobQuery.java +++ b/modules/flowable-job-service-api/src/main/java/org/flowable/job/api/BaseJobQuery.java @@ -86,6 +86,11 @@ public interface BaseJobQuery, T extends Job> exten */ U elementId(String elementId); + /** + * Only select jobs whose element id is one of the given ids. + */ + U elementIds(Collection elementIds); + /** * Only select jobs which exist for the given element name */ @@ -96,6 +101,11 @@ public interface BaseJobQuery, T extends Job> exten */ U scopeId(String scopeId); + /** + * Only select jobs whose scope id is one of the given ids. + */ + U scopeIds(Collection scopeIds); + /** * Only select jobs without a scope id value. **/ diff --git a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java index 264ea57c1af..f9d0051fbbc 100644 --- a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java +++ b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java @@ -51,8 +51,10 @@ public class DeadLetterJobQueryImpl extends AbstractQuery elementIds; protected String elementName; protected String scopeId; + protected Collection scopeIds; protected boolean withoutScopeId; protected String subScopeId; protected String scopeType; @@ -204,6 +206,19 @@ public DeadLetterJobQueryImpl elementId(String elementId) { } return this; } + + @Override + public DeadLetterJobQuery elementIds(Collection elementIds) { + if (elementIds == null) { + throw new FlowableIllegalArgumentException("Provided element ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.elementIds = elementIds; + } else { + this.elementIds = elementIds; + } + return this; + } @Override public DeadLetterJobQueryImpl elementName(String elementName) { @@ -230,6 +245,19 @@ public DeadLetterJobQueryImpl scopeId(String scopeId) { } return this; } + + @Override + public DeadLetterJobQuery scopeIds(Collection scopeIds) { + if (scopeIds == null) { + throw new FlowableIllegalArgumentException("Provided scope ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.scopeIds = scopeIds; + } else { + this.scopeIds = scopeIds; + } + return this; + } @Override public DeadLetterJobQueryImpl withoutScopeId() { @@ -682,6 +710,10 @@ public String getElementId() { return elementId; } + public Collection getElementIds() { + return elementIds; + } + public String getElementName() { return elementName; } @@ -690,6 +722,10 @@ public String getScopeId() { return scopeId; } + public Collection getScopeIds() { + return scopeIds; + } + public boolean isWithoutScopeId() { return withoutScopeId; } diff --git a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/ExternalWorkerJobQueryImpl.java b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/ExternalWorkerJobQueryImpl.java index f4d3136edb1..ac63cd8b4ca 100644 --- a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/ExternalWorkerJobQueryImpl.java +++ b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/ExternalWorkerJobQueryImpl.java @@ -50,8 +50,10 @@ public class ExternalWorkerJobQueryImpl extends AbstractQuery elementIds; protected String elementName; protected String scopeId; + protected Collection scopeIds; protected boolean withoutScopeId; protected String subScopeId; protected String scopeType; @@ -206,6 +208,19 @@ public ExternalWorkerJobQuery elementId(String elementId) { return this; } + @Override + public ExternalWorkerJobQuery elementIds(Collection elementIds) { + if (elementIds == null) { + throw new FlowableIllegalArgumentException("Provided element ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.elementIds = elementIds; + } else { + this.elementIds = elementIds; + } + return this; + } + @Override public ExternalWorkerJobQuery elementName(String elementName) { if (elementName == null) { @@ -231,6 +246,19 @@ public ExternalWorkerJobQueryImpl scopeId(String scopeId) { } return this; } + + @Override + public ExternalWorkerJobQuery scopeIds(Collection scopeIds) { + if (scopeIds == null) { + throw new FlowableIllegalArgumentException("Provided scope ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.scopeIds = scopeIds; + } else { + this.scopeIds = scopeIds; + } + return this; + } @Override public ExternalWorkerJobQuery withoutScopeId() { @@ -670,6 +698,10 @@ public String getElementId() { return elementId; } + public Collection getElementIds() { + return elementIds; + } + public String getElementName() { return elementName; } @@ -677,6 +709,10 @@ public String getElementName() { public String getScopeId() { return scopeId; } + + public Collection getScopeIds() { + return scopeIds; + } public boolean isWithoutScopeId() { return withoutScopeId; diff --git a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java index 17cc7dc2f6e..c6c3df83ca4 100644 --- a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java +++ b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java @@ -52,8 +52,10 @@ public class JobQueryImpl extends AbstractQuery implements JobQue protected String category; protected String categoryLike; protected String elementId; + protected Collection elementIds; protected String elementName; protected String scopeId; + protected Collection scopeIds; protected boolean withoutScopeId; protected String subScopeId; protected String scopeType; @@ -208,6 +210,19 @@ public JobQueryImpl elementId(String elementId) { return this; } + @Override + public JobQuery elementIds(Collection elementIds) { + if (elementIds == null) { + throw new FlowableIllegalArgumentException("Provided element ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.elementIds = elementIds; + } else { + this.elementIds = elementIds; + } + return this; + } + @Override public JobQueryImpl elementName(String elementName) { if (elementName == null) { @@ -233,7 +248,20 @@ public JobQueryImpl scopeId(String scopeId) { } return this; } - + + @Override + public JobQuery scopeIds(Collection scopeIds) { + if (scopeIds == null) { + throw new FlowableIllegalArgumentException("Provided scope ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.scopeIds = scopeIds; + } else { + this.scopeIds = scopeIds; + } + return this; + } + @Override public JobQuery withoutScopeId() { if (inOrStatement) { @@ -673,6 +701,10 @@ public String getElementId() { return elementId; } + public Collection getElementIds() { + return elementIds; + } + public String getElementName() { return elementName; } @@ -680,6 +712,10 @@ public String getElementName() { public String getScopeId() { return scopeId; } + + public Collection getScopeIds() { + return scopeIds; + } public boolean isWithoutScopeId() { return withoutScopeId; diff --git a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java index 4594669d89f..683c5fe634c 100644 --- a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java +++ b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java @@ -51,8 +51,10 @@ public class SuspendedJobQueryImpl extends AbstractQuery protected String category; protected String categoryLike; protected String elementId; + protected Collection elementIds; protected String elementName; protected String scopeId; + protected Collection scopeIds; protected boolean withoutScopeId; protected String subScopeId; protected String scopeType; @@ -207,6 +209,19 @@ public SuspendedJobQueryImpl elementId(String elementId) { } return this; } + + @Override + public SuspendedJobQueryImpl elementIds(Collection elementIds) { + if (elementIds == null) { + throw new FlowableIllegalArgumentException("Provided element ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.elementIds = elementIds; + } else { + this.elementIds = elementIds; + } + return this; + } @Override public SuspendedJobQueryImpl elementName(String elementName) { @@ -233,6 +248,19 @@ public SuspendedJobQueryImpl scopeId(String scopeId) { } return this; } + + @Override + public SuspendedJobQueryImpl scopeIds(Collection scopeIds) { + if (scopeIds == null) { + throw new FlowableIllegalArgumentException("Provided scope ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.scopeIds = scopeIds; + } else { + this.scopeIds = scopeIds; + } + return this; + } @Override public SuspendedJobQueryImpl withoutScopeId() { @@ -740,6 +768,10 @@ public String getElementId() { return elementId; } + public Collection getElementIds() { + return elementIds; + } + public String getElementName() { return elementName; } @@ -747,6 +779,10 @@ public String getElementName() { public String getScopeId() { return scopeId; } + + public Collection getScopeIds() { + return scopeIds; + } public boolean isWithoutScopeId() { return withoutScopeId; diff --git a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/TimerJobQueryImpl.java b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/TimerJobQueryImpl.java index 70df4c0399f..f7ed2694c7a 100644 --- a/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/TimerJobQueryImpl.java +++ b/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/TimerJobQueryImpl.java @@ -51,8 +51,10 @@ public class TimerJobQueryImpl extends AbstractQuery impleme protected String category; protected String categoryLike; protected String elementId; + protected Collection elementIds; protected String elementName; protected String scopeId; + protected Collection scopeIds; protected boolean withoutScopeId; protected String subScopeId; protected String scopeType; @@ -204,6 +206,19 @@ public TimerJobQueryImpl elementId(String elementId) { return this; } + @Override + public TimerJobQuery elementIds(Collection elementIds) { + if (elementIds == null) { + throw new FlowableIllegalArgumentException("Provided element ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.elementIds = elementIds; + } else { + this.elementIds = elementIds; + } + return this; + } + @Override public TimerJobQueryImpl elementName(String elementName) { if (elementName == null) { @@ -229,6 +244,19 @@ public TimerJobQueryImpl scopeId(String scopeId) { } return this; } + + @Override + public TimerJobQuery scopeIds(Collection scopeIds) { + if (scopeIds == null) { + throw new FlowableIllegalArgumentException("Provided scope ids are null"); + } + if (inOrStatement) { + this.currentOrQueryObject.scopeIds = scopeIds; + } else { + this.scopeIds = scopeIds; + } + return this; + } @Override public TimerJobQueryImpl withoutScopeId() { @@ -653,6 +681,10 @@ public String getElementId() { return elementId; } + public Collection getElementIds() { + return elementIds; + } + public String getElementName() { return elementName; } @@ -660,6 +692,10 @@ public String getElementName() { public String getScopeId() { return scopeId; } + + public Collection getScopeIds() { + return scopeIds; + } public boolean isWithoutScopeId() { return withoutScopeId; diff --git a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/DeadLetterJob.xml b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/DeadLetterJob.xml index 9142cda7fe5..8badd07fe86 100644 --- a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/DeadLetterJob.xml +++ b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/DeadLetterJob.xml @@ -284,12 +284,24 @@ and RES.ELEMENT_ID_ = #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_NAME_ = #{elementName, jdbcType=NVARCHAR} and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ IS NULL @@ -396,12 +408,24 @@ or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_NAME_ = #{orQueryObject.elementName, jdbcType=NVARCHAR} or RES.SCOPE_ID_ = #{orQueryObject.scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ IS NULL diff --git a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/ExternalWorkerJob.xml b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/ExternalWorkerJob.xml index 84590cb2d38..1f65b54fda1 100755 --- a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/ExternalWorkerJob.xml +++ b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/ExternalWorkerJob.xml @@ -217,12 +217,24 @@ and RES.ELEMENT_ID_ = #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_NAME_ = #{elementName, jdbcType=NVARCHAR} and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ IS NULL @@ -339,12 +351,24 @@ or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_NAME_ = #{orQueryObject.elementName, jdbcType=NVARCHAR} or RES.SCOPE_ID_ = #{orQueryObject.scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ IS NULL diff --git a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/Job.xml b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/Job.xml index 4d0f07bcd69..a6d34aada59 100755 --- a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/Job.xml +++ b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/Job.xml @@ -176,12 +176,24 @@ and RES.ELEMENT_ID_ = #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_NAME_ = #{elementName, jdbcType=NVARCHAR} and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ IS NULL @@ -291,12 +303,24 @@ or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_NAME_ = #{orQueryObject.elementName, jdbcType=NVARCHAR} or RES.SCOPE_ID_ = #{orQueryObject.scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ IS NULL diff --git a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/SuspendedJob.xml b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/SuspendedJob.xml index 13b8e8bf1e1..abbf342b4d6 100644 --- a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/SuspendedJob.xml +++ b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/SuspendedJob.xml @@ -299,12 +299,24 @@ and RES.ELEMENT_ID_ = #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_NAME_ = #{elementName, jdbcType=NVARCHAR} and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ IS NULL @@ -414,12 +426,24 @@ or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_NAME_ = #{orQueryObject.elementName, jdbcType=NVARCHAR} or RES.SCOPE_ID_ = #{orQueryObject.scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ IS NULL diff --git a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/TimerJob.xml b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/TimerJob.xml index d4a89627a30..d462c27c4b5 100644 --- a/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/TimerJob.xml +++ b/modules/flowable-job-service/src/main/resources/org/flowable/job/service/db/mapping/entity/TimerJob.xml @@ -106,12 +106,24 @@ and RES.ELEMENT_ID_ = #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + and RES.ELEMENT_NAME_ = #{elementName, jdbcType=NVARCHAR} and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + and RES.SCOPE_ID_ IS NULL @@ -215,12 +227,24 @@ or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_ID_ in + + #{elementId, jdbcType=NVARCHAR} + + or RES.ELEMENT_NAME_ = #{orQueryObject.elementName, jdbcType=NVARCHAR} or RES.SCOPE_ID_ = #{orQueryObject.scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ in + + #{scopeId, jdbcType=NVARCHAR} + + or RES.SCOPE_ID_ IS NULL