Skip to content

Commit

Permalink
Merge pull request #3 from HMubaireek/feat/filter-instances-by-multip…
Browse files Browse the repository at this point in the history
…le-variables

feat: filter process instances by multiple variables
  • Loading branch information
HMubaireek authored May 6, 2024
2 parents 926ae3a + b37ae79 commit 52f8925
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 45 deletions.
12 changes: 12 additions & 0 deletions data/src/main/kotlin/io/zeebe/zeeqs/data/entity/VariableFilter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.zeebe.zeeqs.data.entity

enum class EqualityOperation {
EQUALS,
CONTAINS
}

class VariableFilter (
val name: String,
val value: String,
val equalityOperation: EqualityOperation = EqualityOperation.EQUALS
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ interface VariableRepository : PagingAndSortingRepository<Variable, Long> {
@Transactional(readOnly = true)
fun findByProcessInstanceKeyInAndName(processInstanceKey: List<Long>, name: String): List<Variable>


@Transactional(readOnly = true)
fun findByProcessInstanceKeyInAndNameIn(processInstanceKey: List<Long>, name: List<String>): List<Variable>

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package io.zeebe.zeeqs.data.service

import io.zeebe.zeeqs.data.entity.ProcessInstance
import io.zeebe.zeeqs.data.entity.ProcessInstanceState
import io.zeebe.zeeqs.data.entity.Variable
import io.zeebe.zeeqs.data.entity.*
import io.zeebe.zeeqs.data.repository.ProcessInstanceKeyOnly
import io.zeebe.zeeqs.data.repository.ProcessInstanceRepository
import io.zeebe.zeeqs.data.repository.VariableRepository
Expand All @@ -14,26 +12,35 @@ class ProcessInstanceService(
private val processInstancesRepository: ProcessInstanceRepository,
private val variableRepository: VariableRepository) {

private fun getVariables(stateIn: List<ProcessInstanceState>, variableName: String, variableValue: String): List<Variable> {
private fun getVariables(stateIn: List<ProcessInstanceState>, variables: List<VariableFilter>): List<Variable> {
val processInstances = processInstancesRepository.findByStateIn(stateIn).toList();
return getVariablesByProcessInstanceKeys(processInstances, variableName, variableValue);
return getVariablesByProcessInstanceKeys(processInstances, variables);
}

private fun getVariables(stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variableName: String, variableValue: String): List<Variable> {
private fun getVariables(stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variables: List<VariableFilter>): List<Variable> {
val processInstances = processInstancesRepository.findByProcessDefinitionKeyAndStateIn(processDefinitionKey, stateIn).toList();
return getVariablesByProcessInstanceKeys(processInstances, variableName, variableValue);
return getVariablesByProcessInstanceKeys(processInstances, variables);

}

private fun getVariablesByProcessInstanceKeys(processInstances: List<ProcessInstanceKeyOnly>, variableName: String, variableValue: String): List<Variable> {
val variables = variableRepository.findByProcessInstanceKeyInAndName(processInstances.map { it.getKey() }, variableName);
val filteredVariables = variables.filter { it.value == variableValue };
private fun getVariablesByProcessInstanceKeys(processInstances: List<ProcessInstanceKeyOnly>, variables: List<VariableFilter>): List<Variable> {
val variableNames = variables.map { it.name }
val processInstancesKeys = processInstances.map { it.getKey() }
val variablesList = variableRepository.findByProcessInstanceKeyInAndNameIn(processInstancesKeys, variableNames);
val filteredVariables = variablesList.filter { variable ->
variables.any { filter ->
when (filter.equalityOperation) {
EqualityOperation.EQUALS -> variable.name == filter.name && variable.value == filter.value
EqualityOperation.CONTAINS -> variable.name == filter.name && variable.value.contains(filter.value)
}
}
}
return filteredVariables;
}

fun getProcessInstances(perPage: Int, page: Int, stateIn: List<ProcessInstanceState>, variableName: String?, variableValue: String?): List<ProcessInstance> {
if(variableName != null && variableValue != null) {
val filteredVariables = getVariables(stateIn, variableName, variableValue);
fun getProcessInstances(perPage: Int, page: Int, stateIn: List<ProcessInstanceState>, variables: List<VariableFilter>?): List<ProcessInstance> {
if(!variables.isNullOrEmpty()) {
val filteredVariables = getVariables(stateIn, variables);
val filteredProcessInstances = processInstancesRepository.findByStateInAndKeyIn(stateIn, filteredVariables.map { it.processInstanceKey }, PageRequest.of(page, perPage)).toList();
return filteredProcessInstances;
}
Expand All @@ -42,9 +49,9 @@ class ProcessInstanceService(
}
}

fun countProcessInstances(stateIn: List<ProcessInstanceState>, variableName: String?, variableValue: String?): Long {
if(variableName != null && variableValue != null) {
val filteredVariables = getVariables(stateIn, variableName, variableValue);
fun countProcessInstances(stateIn: List<ProcessInstanceState>, variables: List<VariableFilter>?): Long {
if(!variables.isNullOrEmpty()) {
val filteredVariables = getVariables(stateIn, variables);
return filteredVariables.count().toLong();
}

Expand All @@ -54,9 +61,9 @@ class ProcessInstanceService(
}


fun getProcessInstances(perPage: Int, page: Int, stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variableName: String?, variableValue: String?): List<ProcessInstance> {
if(variableName != null && variableValue != null) {
val filteredVariables = getVariables(stateIn, processDefinitionKey, variableName, variableValue);
fun getProcessInstances(perPage: Int, page: Int, stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variables: List<VariableFilter>?): List<ProcessInstance> {
if(!variables.isNullOrEmpty()) {
val filteredVariables = getVariables(stateIn, processDefinitionKey, variables);
val filteredProcessInstances = processInstancesRepository.findByStateInAndKeyIn(stateIn, filteredVariables.map { it.processInstanceKey }, PageRequest.of(page, perPage)).toList();
return filteredProcessInstances;
}
Expand All @@ -65,9 +72,9 @@ class ProcessInstanceService(
}
}

fun countProcessInstances(stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variableName: String?, variableValue: String?): Long {
if(variableName != null && variableValue != null) {
val filteredVariables = getVariables(stateIn, processDefinitionKey, variableName, variableValue);
fun countProcessInstances(stateIn: List<ProcessInstanceState>, processDefinitionKey: Long, variables: List<VariableFilter>?): Long {
if(!variables.isNullOrEmpty()) {
val filteredVariables = getVariables(stateIn, processDefinitionKey, variables);
return filteredVariables.count().toLong();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,15 @@ class ProcessService(val processRepository: ProcessRepository) {
}

private fun getExtensionProperties(element: BaseElement): Collection<BpmnElementExtensionProperties>? {
return element.extensionElements?.elementsQuery
return element.extensionElements?.elementsQuery
?.filterByType(ZeebeProperties::class.java)
?.singleResult()
?.properties
?.map { BpmnElementExtensionProperties(name = it.name, value = it.value) }
?.findSingleResult()
?.map { properties ->
properties.properties?.map { property ->
BpmnElementExtensionProperties(name = property.name, value = property.value)
}
}
?.orElse(null)
}


Expand Down
10 changes: 5 additions & 5 deletions data/src/test/kotlin/io/zeebe/zeeqs/ProcessServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ class ProcessServiceTest(
// then
assertThat(info)
.isNotNull()
.contains(entry("s", BpmnElementInfo("s", "start", BpmnElementType.START_EVENT, BpmnElementMetadata(), listOf(BpmnElementExtensionProperties()), "")))
.contains(entry("t", BpmnElementInfo("t", "task", BpmnElementType.SERVICE_TASK, BpmnElementMetadata(jobType = "test"), listOf(BpmnElementExtensionProperties()), "")))
.contains(entry("s", BpmnElementInfo("s", "start", BpmnElementType.START_EVENT, BpmnElementMetadata(), null, "")))
.contains(entry("t", BpmnElementInfo("t", "task", BpmnElementType.SERVICE_TASK, BpmnElementMetadata(jobType = "test"), null, "")))
.contains(entry("u", BpmnElementInfo("u", "userTask", BpmnElementType.USER_TASK, BpmnElementMetadata(
userTaskAssignmentDefinition = UserTaskAssignmentDefinition(assignee = "user1", candidateGroups = "group1")), listOf(BpmnElementExtensionProperties()), ""))
userTaskAssignmentDefinition = UserTaskAssignmentDefinition(assignee = "user1", candidateGroups = "group1")), null, ""))
)
.contains(entry("e", BpmnElementInfo("e", null, BpmnElementType.END_EVENT, BpmnElementMetadata(), listOf(BpmnElementExtensionProperties()), "")))
.contains(entry("e", BpmnElementInfo("e", null, BpmnElementType.END_EVENT, BpmnElementMetadata(), null, "")))
}

@Test
Expand Down Expand Up @@ -91,7 +91,7 @@ class ProcessServiceTest(
resource = """{"x":1}"""
)
),
listOf(BpmnElementExtensionProperties()), ""
null, ""
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.zeebe.zeeqs.graphql.resolvers.query

import io.zeebe.zeeqs.data.entity.ProcessInstance
import io.zeebe.zeeqs.data.entity.ProcessInstanceState
import io.zeebe.zeeqs.data.entity.VariableFilter
import io.zeebe.zeeqs.data.repository.ProcessInstanceRepository
import io.zeebe.zeeqs.data.service.ProcessInstanceService
import io.zeebe.zeeqs.graphql.resolvers.connection.ProcessInstanceConnection
Expand All @@ -22,12 +23,11 @@ class ProcessInstanceQueryResolver(
@Argument perPage: Int,
@Argument page: Int,
@Argument stateIn: List<ProcessInstanceState>,
@Argument variableName: String?,
@Argument variableValue: String?
@Argument variables: List<VariableFilter>?
): ProcessInstanceConnection {
return ProcessInstanceConnection(
getItems = { processInstanceService.getProcessInstances(perPage, page, stateIn, variableName, variableValue) },
getCount = { processInstanceService.countProcessInstances(stateIn, variableName, variableValue) }
getItems = { processInstanceService.getProcessInstances(perPage, page, stateIn, variables) },
getCount = { processInstanceService.countProcessInstances(stateIn, variables) }
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ class ProcessResolver(
@Argument perPage: Int,
@Argument page: Int,
@Argument stateIn: List<ProcessInstanceState>,
@Argument variableName: String?,
@Argument variableValue: String?
@Argument variables: List<VariableFilter>?
): ProcessInstanceConnection {
return ProcessInstanceConnection(
getItems = {
Expand All @@ -40,16 +39,14 @@ class ProcessResolver(
page,
stateIn,
process.key,
variableName,
variableValue
variables
).toList()
},
getCount = {
processInstanceService.countProcessInstances(
stateIn,
process.key,
variableName,
variableValue
variables
)
}
)
Expand Down
3 changes: 1 addition & 2 deletions graphql-api/src/main/resources/graphql/Process.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ type Process {
perPage: Int = 10,
page: Int = 0,
stateIn: [ProcessInstanceState!] = [ACTIVATED, COMPLETED, TERMINATED]
variableName: String = null,
variableValue: String = null): ProcessInstanceConnection!
variables: [VariableFilter] = null): ProcessInstanceConnection!
# the scheduled timers of the timer start events of the process
timers: [Timer!]
# the opened message subscriptions of the message start events of the process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ type Query {
perPage: Int = 10,
page: Int = 0,
stateIn: [ProcessInstanceState!] = [ACTIVATED, COMPLETED, TERMINATED],
variableName: String = null,
variableValue: String = null
variables: [VariableFilter] = null
): ProcessInstanceConnection!

}
Expand Down
12 changes: 12 additions & 0 deletions graphql-api/src/main/resources/graphql/Variable.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ type VariableUpdate {
value: String!
timestamp(zoneId: String = "Z"): String!
}

input VariableFilter {
name: String!,
value: String!,
equalityOperation: EqualityOperation = EQUALS
}

# The type of a variable value filter
enum EqualityOperation {
EQUALS,
CONTAINS
}

0 comments on commit 52f8925

Please sign in to comment.