diff --git a/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/QueryCloudProcessInstanceImpl.java b/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/QueryCloudProcessInstanceImpl.java new file mode 100644 index 00000000000..804c421383b --- /dev/null +++ b/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/QueryCloudProcessInstanceImpl.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.api.process.model.impl; + +import java.util.Objects; +import java.util.Set; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudSubprocessInstance; + +public class QueryCloudProcessInstanceImpl extends CloudProcessInstanceImpl implements QueryCloudProcessInstance { + + private Set subprocesses; + + @Override + public Set getSubprocesses() { + return subprocesses; + } + + @Override + public void setSubprocesses(Set subprocesses) { + this.subprocesses = subprocesses; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + QueryCloudProcessInstanceImpl other = (QueryCloudProcessInstanceImpl) obj; + return Objects.equals(subprocesses, other.subprocesses); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), subprocesses); + } +} diff --git a/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/conf/CloudProcessModelAutoConfiguration.java b/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/conf/CloudProcessModelAutoConfiguration.java index 4de5b0218f7..40cb85de107 100644 --- a/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/conf/CloudProcessModelAutoConfiguration.java +++ b/activiti-cloud-api/activiti-cloud-api-process-model-impl/src/main/java/org/activiti/cloud/api/process/model/impl/conf/CloudProcessModelAutoConfiguration.java @@ -50,6 +50,7 @@ import org.activiti.cloud.api.process.model.IntegrationError; import org.activiti.cloud.api.process.model.IntegrationRequest; import org.activiti.cloud.api.process.model.IntegrationResult; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; import org.activiti.cloud.api.process.model.impl.CloudApplicationImpl; import org.activiti.cloud.api.process.model.impl.CloudBPMNActivityImpl; import org.activiti.cloud.api.process.model.impl.CloudIntegrationContextImpl; @@ -60,6 +61,7 @@ import org.activiti.cloud.api.process.model.impl.IntegrationErrorImpl; import org.activiti.cloud.api.process.model.impl.IntegrationRequestImpl; import org.activiti.cloud.api.process.model.impl.IntegrationResultImpl; +import org.activiti.cloud.api.process.model.impl.QueryCloudProcessInstanceImpl; import org.activiti.cloud.api.process.model.impl.SyncCloudProcessDefinitionsPayload; import org.activiti.cloud.api.process.model.impl.SyncCloudProcessDefinitionsResult; import org.activiti.cloud.api.process.model.impl.events.CloudApplicationDeployedEventImpl; @@ -320,6 +322,7 @@ public JavaType resolveAbstractType(DeserializationConfig config, BeanDescriptio resolver.addMapping(CloudServiceTask.class, CloudServiceTaskImpl.class); resolver.addMapping(Deployment.class, DeploymentImpl.class); resolver.addMapping(CloudApplication.class, CloudApplicationImpl.class); + resolver.addMapping(QueryCloudProcessInstance.class, QueryCloudProcessInstanceImpl.class); module.setAbstractTypes(resolver); diff --git a/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudProcessInstance.java b/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudProcessInstance.java new file mode 100644 index 00000000000..73adac76879 --- /dev/null +++ b/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudProcessInstance.java @@ -0,0 +1,24 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.api.process.model; + +import java.util.Set; + +public interface QueryCloudProcessInstance extends CloudProcessInstance { + Set getSubprocesses(); + + void setSubprocesses(Set subprocesses); +} diff --git a/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudSubprocessInstance.java b/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudSubprocessInstance.java new file mode 100644 index 00000000000..ff6b3b89d51 --- /dev/null +++ b/activiti-cloud-api/activiti-cloud-api-process-model/src/main/java/org/activiti/cloud/api/process/model/QueryCloudSubprocessInstance.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.api.process.model; + +public class QueryCloudSubprocessInstance { + + private String id; + private String processDefinitionName; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getProcessDefinitionName() { + return processDefinitionName; + } + + public void setProcessDefinitionName(String processDefinitionName) { + this.processDefinitionName = processDefinitionName; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessInstanceEntity.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessInstanceEntity.java index 5782a501597..a254db7690b 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessInstanceEntity.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessInstanceEntity.java @@ -45,7 +45,8 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudSubprocessInstance; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Filter; @@ -74,7 +75,7 @@ ), } ) -public class ProcessInstanceEntity extends ActivitiEntityMetadata implements CloudProcessInstance { +public class ProcessInstanceEntity extends ActivitiEntityMetadata implements QueryCloudProcessInstance { @Id private String id; @@ -221,6 +222,9 @@ public class ProcessInstanceEntity extends ActivitiEntityMetadata implements Clo private String parentId; + @Transient + private Set subprocesses; + public ProcessInstanceEntity() {} public ProcessInstanceEntity( @@ -510,4 +514,13 @@ public boolean equals(Object obj) { return id != null && Objects.equals(id, other.id); } + + @Override + public Set getSubprocesses() { + return subprocesses; + } + + public void setSubprocesses(Set subprocesses) { + this.subprocesses = subprocesses; + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepository.java new file mode 100644 index 00000000000..a4b0f3cf00b --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepository.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.app.repository; + +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface CustomizedProcessInstanceRepository { + Page mapSubprocesses(Page processInstances, Pageable pageable); + + ProcessInstanceEntity mapSubprocesses(ProcessInstanceEntity processInstance); +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImpl.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImpl.java new file mode 100644 index 00000000000..13a2c6b9937 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImpl.java @@ -0,0 +1,144 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.app.repository; + +import com.querydsl.jpa.JPQLQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.activiti.cloud.api.process.model.QueryCloudSubprocessInstance; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.QProcessInstanceEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.Querydsl; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +import org.springframework.data.support.PageableExecutionUtils; + +public class CustomizedProcessInstanceRepositoryImpl + extends QuerydslRepositorySupport + implements CustomizedProcessInstanceRepository { + + private final JPAQueryFactory queryFactory; + + public CustomizedProcessInstanceRepositoryImpl(EntityManager entityManager) { + super(ProcessInstanceEntity.class); + this.queryFactory = new JPAQueryFactory(entityManager); + } + + @Override + public Page mapSubprocesses( + Page processInstances, + Pageable pageable + ) { + List parentIds = getParentIds(processInstances); + + Page subprocesses = findSubprocessesByParentIds(parentIds, pageable); + + Map> subprocessMap = groupSubprocesses(subprocesses); + + setSubprocesses(processInstances, subprocessMap); + + return processInstances; + } + + @Override + public ProcessInstanceEntity mapSubprocesses(ProcessInstanceEntity processInstance) { + List subprocesses = findSubprocessesByParentId(processInstance.getId()); + + if (subprocesses == null || subprocesses.isEmpty()) { + processInstance.setSubprocesses(new HashSet<>()); + return processInstance; + } + + Set subprocessSet = subprocesses + .stream() + .map(this::getQueryCloudSubprocessInstance) + .collect(Collectors.toSet()); + + processInstance.setSubprocesses(subprocessSet); + + return processInstance; + } + + public QueryCloudSubprocessInstance getQueryCloudSubprocessInstance(ProcessInstanceEntity subprocess) { + QueryCloudSubprocessInstance subProcessInstance = new QueryCloudSubprocessInstance(); + subProcessInstance.setId(subprocess.getId()); + subProcessInstance.setProcessDefinitionName(subprocess.getProcessDefinitionName()); + return subProcessInstance; + } + + public List getParentIds(Page processInstances) { + return processInstances.getContent().stream().map(ProcessInstanceEntity::getId).toList(); + } + + public Map> groupSubprocesses(Page subprocesses) { + return subprocesses + .getContent() + .stream() + .collect( + Collectors.groupingBy( + ProcessInstanceEntity::getParentId, + Collectors.mapping(this::getQueryCloudSubprocessInstance, Collectors.toSet()) + ) + ); + } + + public void setSubprocesses( + Page processInstances, + Map> subprocessMap + ) { + processInstances + .getContent() + .forEach(processInstance -> { + Set subprocessSet = subprocessMap.getOrDefault( + processInstance.getId(), + Set.of() + ); + processInstance.setSubprocesses(subprocessSet); + }); + } + + public Page findSubprocessesByParentIds(List parentIds, Pageable pageable) { + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + Querydsl querydsl = getQuerydsl(); + + JPQLQuery subprocessQuery = queryFactory + .selectFrom(processInstanceEntity) + .where(processInstanceEntity.parentId.in(parentIds)); + + long totalElements = subprocessQuery.fetchCount(); + + assert querydsl != null; + List subprocesses = querydsl.applyPagination(pageable, subprocessQuery).fetch(); + + return PageableExecutionUtils.getPage(subprocesses, pageable, () -> totalElements); + } + + public List findSubprocessesByParentId(String parentId) { + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + return queryFactory + .selectFrom(processInstanceEntity) + .where(processInstanceEntity.parentId.eq(parentId)) + .fetch(); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java index 919e38fd68e..5e167fe76a9 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java @@ -38,6 +38,7 @@ public interface ProcessInstanceRepository JpaSpecificationExecutor, QuerydslPredicateExecutor, QuerydslBinderCustomizer, + CustomizedProcessInstanceRepository, CrudRepository { @Override default void customize(QuerydslBindings bindings, QProcessInstanceEntity root) { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImplTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImplTest.java new file mode 100644 index 00000000000..0cc5ecd04d5 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/CustomizedProcessInstanceRepositoryImplTest.java @@ -0,0 +1,204 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.app.repository; + +import static org.activiti.cloud.services.query.app.repository.utils.ProcessInstanceHelper.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import java.util.*; +import org.activiti.cloud.api.process.model.QueryCloudSubprocessInstance; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.QProcessInstanceEntity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.Querydsl; +import org.springframework.test.util.ReflectionTestUtils; + +@ExtendWith(MockitoExtension.class) +class CustomizedProcessInstanceRepositoryImplTest { + + @Mock + private EntityManager entityManager; + + @Mock + private JPAQueryFactory queryFactory; + + @Mock + private JPAQuery jpaQuery; + + @Mock + private Querydsl querydsl; + + private CustomizedProcessInstanceRepositoryImpl repository; + + @BeforeEach + void setUp() { + repository = new CustomizedProcessInstanceRepositoryImpl(entityManager); + ReflectionTestUtils.setField(repository, "queryFactory", queryFactory); + ReflectionTestUtils.setField(repository, "querydsl", querydsl); + } + + @Test + void testGetQueryCloudSubprocessInstance() { + ProcessInstanceEntity subprocess = createProcessInstance(UUID.randomUUID().toString()); + QueryCloudSubprocessInstance result = repository.getQueryCloudSubprocessInstance(subprocess); + + assertThat(result).isNotNull(); + assertThat(result.getId()).isNotNull(); + assertThat(result.getProcessDefinitionName()).isNotNull(); + } + + @Test + void testGetParentIds() { + List processInstancesList = createParentProcessInstances(3); + Page processInstances = new PageImpl<>(processInstancesList); + + List result = repository.getParentIds(processInstances); + + assertThat(result).isNotNull(); + assertThat(result).hasSize(3); + } + + @Test + void testGroupSubprocesses() { + List processInstancesList = createParentProcessInstances(4); + String parentIdOne = processInstancesList.getFirst().getId(); + String parentIdTwo = processInstancesList.getLast().getId(); + List subprocessesList = createSubprocessInstances(2, parentIdOne); + subprocessesList.addAll(createSubprocessInstances(3, parentIdTwo)); + + Page subprocesses = new PageImpl<>(subprocessesList); + + Map> result = repository.groupSubprocesses(subprocesses); + + assertThat(result).isNotNull(); + assertThat(result).hasSize(2); + assertThat(result).containsKey(parentIdOne); + assertThat(result).containsKey(parentIdTwo); + assertThat(result.get(parentIdOne)).hasSize(2); + assertThat(result.get(parentIdTwo)).hasSize(3); + } + + @Test + void testFindSubprocessesByParentId() { + String parentId = UUID.randomUUID().toString(); + List expectedSubprocesses = createSubprocessInstances(2, parentId); + + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + when(queryFactory.selectFrom(processInstanceEntity)).thenReturn(jpaQuery); + when(jpaQuery.where(processInstanceEntity.parentId.eq(parentId))).thenReturn(jpaQuery); + when(jpaQuery.fetch()).thenReturn(expectedSubprocesses); + + List result = repository.findSubprocessesByParentId(parentId); + + assertThat(result).isNotNull(); + assertThat(result).hasSize(2); + assertThat(result.get(0).getId()).isNotNull(); + assertThat(result.get(1).getId()).isNotNull(); + + verify(queryFactory).selectFrom(processInstanceEntity); + verify(jpaQuery).where(processInstanceEntity.parentId.eq(parentId)); + verify(jpaQuery).fetch(); + } + + @Test + void testFindSubprocessesByParentIds() { + List parentIds = Arrays.asList("parent1", "parent2"); + Pageable pageable = PageRequest.of(0, 10); + + List expectedSubprocesses = createSubprocessInstances(2, "parent1"); + expectedSubprocesses.addAll(createSubprocessInstances(3, "parent2")); + + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + when(queryFactory.selectFrom(processInstanceEntity)).thenReturn(jpaQuery); + when(jpaQuery.where(processInstanceEntity.parentId.in(parentIds))).thenReturn(jpaQuery); + when(jpaQuery.fetch()).thenReturn(expectedSubprocesses); + when(querydsl.applyPagination(pageable, jpaQuery)).thenReturn(jpaQuery); + + Page result = repository.findSubprocessesByParentIds(parentIds, pageable); + + assertThat(result).isNotNull(); + assertThat(result.getTotalElements()).isEqualTo(5); + assertThat(result.getContent().get(0).getId()).isNotNull(); + assertThat(result.getContent().get(1).getId()).isNotNull(); + + verify(queryFactory).selectFrom(processInstanceEntity); + verify(jpaQuery).where(processInstanceEntity.parentId.in(parentIds)); + verify(jpaQuery).fetch(); + } + + @Test + void testMapSubprocesses() { + List processInstancesList = createParentProcessInstances(2); + List parentIds = Arrays.asList( + processInstancesList.getFirst().getId(), + processInstancesList.getLast().getId() + ); + Page processInstances = new PageImpl<>(processInstancesList); + Pageable pageable = PageRequest.of(0, 10); + + List subprocessesList = createSubprocessInstances( + 2, + processInstancesList.get(0).getId() + ); + subprocessesList.addAll(createSubprocessInstances(3, processInstancesList.get(1).getId())); + + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + when(queryFactory.selectFrom(processInstanceEntity)).thenReturn(jpaQuery); + when(jpaQuery.where(processInstanceEntity.parentId.in(parentIds))).thenReturn(jpaQuery); + when(jpaQuery.fetch()).thenReturn(subprocessesList); + when(querydsl.applyPagination(pageable, jpaQuery)).thenReturn(jpaQuery); + + Page result = repository.mapSubprocesses(processInstances, pageable); + + assertThat(result).isNotNull(); + assertThat(result.getTotalElements()).isEqualTo(2); + assertThat(result.getContent().get(0).getSubprocesses()).isNotNull(); + assertThat(result.getContent().get(1).getSubprocesses()).isNotNull(); + } + + @Test + void testMapSubprocessesForProcessInstance() { + ProcessInstanceEntity entity = createProcessInstance("1"); + String parentId = entity.getId(); + List expectedSubprocesses = createSubprocessInstances(2, parentId); + + QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity; + + when(queryFactory.selectFrom(processInstanceEntity)).thenReturn(jpaQuery); + when(jpaQuery.where(processInstanceEntity.parentId.eq(parentId))).thenReturn(jpaQuery); + when(jpaQuery.fetch()).thenReturn(expectedSubprocesses); + + ProcessInstanceEntity result = repository.mapSubprocesses(entity); + + assertThat(result).isNotNull(); + assertThat(result.getSubprocesses()).hasSize(2); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/utils/ProcessInstanceHelper.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/utils/ProcessInstanceHelper.java new file mode 100644 index 00000000000..6bb86e7b4e4 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/utils/ProcessInstanceHelper.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.app.repository.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; + +public class ProcessInstanceHelper { + + private ProcessInstanceHelper() {} + + public static ProcessInstanceEntity createProcessInstance(String parentId) { + ProcessInstanceEntity entity = new ProcessInstanceEntity(); + entity.setId(UUID.randomUUID().toString()); + entity.setName(UUID.randomUUID().toString()); + entity.setProcessDefinitionName("process-definition"); + entity.setParentId(parentId.equals("1") ? null : parentId); + return entity; + } + + public static List createParentProcessInstances(int count) { + List instances = new ArrayList<>(); + for (int i = 0; i < count; i++) { + instances.add(createProcessInstance("1")); + } + return instances; + } + + public static List createSubprocessInstances(int count, String parentId) { + List instances = new ArrayList<>(); + for (int i = 0; i < count; i++) { + instances.add(createProcessInstance(parentId)); + } + return instances; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java index 01a151d582b..475092d5eba 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java @@ -39,6 +39,8 @@ import org.activiti.cloud.services.query.rest.assembler.ServiceTaskRepresentationModelAssembler; import org.activiti.cloud.services.query.rest.assembler.TaskRepresentationModelAssembler; import org.activiti.cloud.services.query.rest.assembler.TaskVariableRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceAdminControllerHelper; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceControllerHelper; import org.activiti.cloud.services.query.rest.predicate.QueryDslPredicateAggregator; import org.activiti.cloud.services.security.ProcessDefinitionFilter; import org.activiti.cloud.services.security.ProcessDefinitionKeyBasedRestrictionBuilder; @@ -292,4 +294,27 @@ public ProcessInstanceAdminService processInstanceAdminService( new QueryDslPredicateAggregator() ); } + + @Bean + @ConditionalOnMissingBean + public ProcessInstanceControllerHelper processInstanceControllerHelper( + ProcessInstanceRepository processInstanceRepository, + ProcessInstanceService processInstanceService + ) { + return new ProcessInstanceControllerHelper(processInstanceRepository, processInstanceService); + } + + @Bean + @ConditionalOnMissingBean + public ProcessInstanceAdminControllerHelper processInstanceAdminControllerHelper( + ProcessInstanceRepository processInstanceRepository, + ProcessInstanceAdminService processInstanceAdminService, + ProcessInstanceControllerHelper processInstanceControllerHelper + ) { + return new ProcessInstanceAdminControllerHelper( + processInstanceRepository, + processInstanceAdminService, + processInstanceControllerHelper + ); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java index f31b51ccf32..d72d29a839c 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java @@ -29,10 +29,11 @@ import java.util.Optional; import java.util.Set; import org.activiti.cloud.alfresco.data.domain.AlfrescoPagedModelAssembler; -import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; import org.activiti.cloud.services.query.model.JsonViews; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.rest.assembler.ProcessInstanceRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceAdminControllerHelper; import org.activiti.cloud.services.query.rest.payload.ProcessInstanceQueryBody; import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -60,25 +61,29 @@ public class ProcessInstanceAdminController { private final ProcessInstanceAdminService processInstanceAdminService; - private ProcessInstanceRepresentationModelAssembler processInstanceRepresentationModelAssembler; + private final ProcessInstanceRepresentationModelAssembler processInstanceRepresentationModelAssembler; - private AlfrescoPagedModelAssembler pagedCollectionModelAssembler; + private final AlfrescoPagedModelAssembler pagedCollectionModelAssembler; + + private final ProcessInstanceAdminControllerHelper processInstanceAdminControllerHelper; @Autowired public ProcessInstanceAdminController( ProcessInstanceAdminService processInstanceAdminService, ProcessInstanceRepresentationModelAssembler processInstanceRepresentationModelAssembler, - AlfrescoPagedModelAssembler pagedCollectionModelAssembler + AlfrescoPagedModelAssembler pagedCollectionModelAssembler, + ProcessInstanceAdminControllerHelper processInstanceAdminControllerHelper ) { this.processInstanceAdminService = processInstanceAdminService; this.processInstanceRepresentationModelAssembler = processInstanceRepresentationModelAssembler; this.pagedCollectionModelAssembler = pagedCollectionModelAssembler; + this.processInstanceAdminControllerHelper = processInstanceAdminControllerHelper; } @Operation(summary = "Find process instances", hidden = true) @JsonView(JsonViews.General.class) @RequestMapping(method = RequestMethod.GET, params = "!variableKeys") - public PagedModel> findAllProcessInstanceAdmin( + public PagedModel> findAllProcessInstanceAdmin( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class ) Predicate predicate, @@ -86,7 +91,7 @@ public PagedModel> findAllProcessInstanceAdmin ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceAdminService.findAll(predicate, pageable), + processInstanceAdminControllerHelper.findAllProcessInstanceAdmin(predicate, pageable), processInstanceRepresentationModelAssembler ); } @@ -94,7 +99,7 @@ public PagedModel> findAllProcessInstanceAdmin @Operation(summary = "Find process instances") @JsonView(JsonViews.ProcessVariables.class) @RequestMapping(method = RequestMethod.GET, params = "variableKeys") - public PagedModel> findAllWithVariablesAdmin( + public PagedModel> findAllWithVariablesAdmin( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class ) Predicate predicate, @@ -107,7 +112,11 @@ public PagedModel> findAllWithVariablesAdmin( ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceAdminService.findAllWithVariables(predicate, variableKeys, pageable), + processInstanceAdminControllerHelper.findAllProcessInstanceAdminWithVariables( + predicate, + variableKeys, + pageable + ), processInstanceRepresentationModelAssembler ); } @@ -122,7 +131,7 @@ public MappingJacksonValue findAllFromBodyProcessAdmin( ) { ProcessInstanceQueryBody queryBody = Optional.ofNullable(payload).orElse(new ProcessInstanceQueryBody()); - PagedModel> pagedModel = pagedCollectionModelAssembler.toModel( + PagedModel> pagedModel = pagedCollectionModelAssembler.toModel( pageable, processInstanceAdminService.findAllFromBody( predicate, @@ -146,7 +155,7 @@ public MappingJacksonValue findAllFromBodyProcessAdmin( @Operation(summary = "Search process instances") @JsonView(JsonViews.ProcessVariables.class) @PostMapping("/search") - public PagedModel> searchProcessInstances( + public PagedModel> searchProcessInstances( @RequestBody ProcessInstanceSearchRequest searchRequest, Pageable pageable ) { @@ -159,9 +168,9 @@ public PagedModel> searchProcessInstances( @JsonView(JsonViews.General.class) @RequestMapping(value = "/{processInstanceId}", method = RequestMethod.GET) - public EntityModel findByIdProcessAdmin(@PathVariable String processInstanceId) { + public EntityModel findByIdProcessAdmin(@PathVariable String processInstanceId) { return processInstanceRepresentationModelAssembler.toModel( - processInstanceAdminService.findById(processInstanceId) + processInstanceAdminControllerHelper.findByIdProcessAdmin(processInstanceId) ); } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java index b5b36cdeb5f..f3d972d2b5c 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java @@ -26,10 +26,11 @@ import io.swagger.v3.oas.annotations.Parameter; import java.util.List; import org.activiti.cloud.alfresco.data.domain.AlfrescoPagedModelAssembler; -import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; import org.activiti.cloud.services.query.model.JsonViews; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.rest.assembler.ProcessInstanceRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceControllerHelper; import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; @@ -57,23 +58,23 @@ public class ProcessInstanceController { private final AlfrescoPagedModelAssembler pagedCollectionModelAssembler; - private final ProcessInstanceService processInstanceService; + private final ProcessInstanceControllerHelper processInstanceControllerHelper; @Autowired public ProcessInstanceController( ProcessInstanceRepresentationModelAssembler processInstanceRepresentationModelAssembler, AlfrescoPagedModelAssembler pagedCollectionModelAssembler, - ProcessInstanceService processInstanceService + ProcessInstanceControllerHelper processInstanceControllerHelper ) { this.processInstanceRepresentationModelAssembler = processInstanceRepresentationModelAssembler; this.pagedCollectionModelAssembler = pagedCollectionModelAssembler; - this.processInstanceService = processInstanceService; + this.processInstanceControllerHelper = processInstanceControllerHelper; } @Operation(summary = "Find process instances", hidden = true) @JsonView(JsonViews.General.class) @RequestMapping(method = RequestMethod.GET, params = "!variableKeys") - public PagedModel> findAllProcessInstances( + public PagedModel> findAllProcessInstances( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class ) Predicate predicate, @@ -81,7 +82,7 @@ public PagedModel> findAllProcessInstances( ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceService.findAll(predicate, pageable), + processInstanceControllerHelper.findAllProcessInstances(predicate, pageable), processInstanceRepresentationModelAssembler ); } @@ -89,7 +90,7 @@ public PagedModel> findAllProcessInstances( @Operation(summary = "Find process instances") @JsonView(JsonViews.ProcessVariables.class) @RequestMapping(method = RequestMethod.GET, params = "variableKeys") - public PagedModel> findAllWithVariables( + public PagedModel> findAllWithVariables( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class ) Predicate predicate, @@ -102,7 +103,7 @@ public PagedModel> findAllWithVariables( ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceService.findAllWithVariables(predicate, variableKeys, pageable), + processInstanceControllerHelper.findAllProcessInstancesWithVariables(predicate, variableKeys, pageable), processInstanceRepresentationModelAssembler ); } @@ -110,26 +111,28 @@ public PagedModel> findAllWithVariables( @Operation(summary = "Search process instances") @JsonView(JsonViews.ProcessVariables.class) @PostMapping("/search") - public PagedModel> searchProcessInstances( + public PagedModel> searchProcessInstances( @RequestBody ProcessInstanceSearchRequest searchRequest, Pageable pageable ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceService.search(searchRequest, pageable), + processInstanceControllerHelper.searchProcessInstances(searchRequest, pageable), processInstanceRepresentationModelAssembler ); } @JsonView(JsonViews.General.class) @RequestMapping(value = "/{processInstanceId}", method = RequestMethod.GET) - public EntityModel findByIdProcess(@PathVariable String processInstanceId) { - return processInstanceRepresentationModelAssembler.toModel(processInstanceService.findById(processInstanceId)); + public EntityModel findByIdProcess(@PathVariable String processInstanceId) { + return processInstanceRepresentationModelAssembler.toModel( + processInstanceControllerHelper.findById(processInstanceId) + ); } @JsonView(JsonViews.General.class) @RequestMapping(value = "/{processInstanceId}/subprocesses", method = RequestMethod.GET) - public PagedModel> subprocesses( + public PagedModel> subprocesses( @PathVariable String processInstanceId, @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class @@ -138,7 +141,7 @@ public PagedModel> subprocesses( ) { return pagedCollectionModelAssembler.toModel( pageable, - processInstanceService.subprocesses(processInstanceId, predicate, pageable), + processInstanceControllerHelper.searchSubprocesses(processInstanceId, predicate, pageable), processInstanceRepresentationModelAssembler ); } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceDeleteController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceDeleteController.java index 963bc7f136c..9ea3c89b9b0 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceDeleteController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceDeleteController.java @@ -25,7 +25,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Optional; -import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; import org.activiti.cloud.services.query.app.repository.*; import org.activiti.cloud.services.query.model.JsonViews; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; @@ -85,12 +85,12 @@ public ProcessInstanceDeleteController( @JsonView(JsonViews.General.class) @RequestMapping(method = RequestMethod.DELETE) @Transactional - public CollectionModel> deleteProcessInstances( + public CollectionModel> deleteProcessInstances( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( root = ProcessInstanceEntity.class ) Predicate predicate ) { - Collection> result = new ArrayList<>(); + Collection> result = new ArrayList<>(); Iterable iterable = processInstanceRepository.findAll(predicate); for (ProcessInstanceEntity entity : iterable) { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/assembler/ProcessInstanceRepresentationModelAssembler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/assembler/ProcessInstanceRepresentationModelAssembler.java index 46e7eba3510..146db92e3ba 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/assembler/ProcessInstanceRepresentationModelAssembler.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/assembler/ProcessInstanceRepresentationModelAssembler.java @@ -18,7 +18,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; -import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.QueryCloudProcessInstance; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.rest.ProcessInstanceController; import org.activiti.cloud.services.query.rest.ProcessInstanceTasksController; @@ -28,10 +28,10 @@ import org.springframework.hateoas.server.RepresentationModelAssembler; public class ProcessInstanceRepresentationModelAssembler - implements RepresentationModelAssembler> { + implements RepresentationModelAssembler> { @Override - public EntityModel toModel(ProcessInstanceEntity entity) { + public EntityModel toModel(ProcessInstanceEntity entity) { Link selfRel = linkTo(methodOn(ProcessInstanceController.class).findByIdProcess(entity.getId())).withSelfRel(); Link tasksRel = linkTo(methodOn(ProcessInstanceTasksController.class).getTasks(entity.getId(), null)) .withRel("tasks"); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceAdminControllerHelper.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceAdminControllerHelper.java new file mode 100644 index 00000000000..c03004d6b54 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceAdminControllerHelper.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest.helper; + +import com.querydsl.core.types.Predicate; +import java.util.List; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.rest.ProcessInstanceAdminService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public class ProcessInstanceAdminControllerHelper { + + private final ProcessInstanceRepository processInstanceRepository; + private final ProcessInstanceAdminService processInstanceAdminService; + private final ProcessInstanceControllerHelper processInstanceControllerHelper; + + public ProcessInstanceAdminControllerHelper( + ProcessInstanceRepository processInstanceRepository, + ProcessInstanceAdminService processInstanceAdminService, + ProcessInstanceControllerHelper processInstanceControllerHelper + ) { + this.processInstanceRepository = processInstanceRepository; + this.processInstanceAdminService = processInstanceAdminService; + this.processInstanceControllerHelper = processInstanceControllerHelper; + } + + public Page findAllProcessInstanceAdmin(Predicate predicate, Pageable pageable) { + Page processInstances = processInstanceAdminService.findAll(predicate, pageable); + return processInstanceControllerHelper.mapAllSubprocesses(processInstances, pageable); + } + + public Page findAllProcessInstanceAdminWithVariables( + Predicate predicate, + List variableKeys, + Pageable pageable + ) { + Page processInstances = processInstanceAdminService.findAllWithVariables( + predicate, + variableKeys, + pageable + ); + return processInstanceControllerHelper.mapAllSubprocesses(processInstances, pageable); + } + + public ProcessInstanceEntity findByIdProcessAdmin(String processInstanceId) { + ProcessInstanceEntity processInstance = processInstanceAdminService.findById(processInstanceId); + return processInstanceRepository.mapSubprocesses(processInstance); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceControllerHelper.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceControllerHelper.java new file mode 100644 index 00000000000..f4be18dd0a0 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/helper/ProcessInstanceControllerHelper.java @@ -0,0 +1,90 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest.helper; + +import com.querydsl.core.types.Predicate; +import java.util.List; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.rest.ProcessInstanceService; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public class ProcessInstanceControllerHelper { + + private final ProcessInstanceRepository processInstanceRepository; + private final ProcessInstanceService processInstanceService; + + public ProcessInstanceControllerHelper( + ProcessInstanceRepository processInstanceRepository, + ProcessInstanceService processInstanceService + ) { + this.processInstanceRepository = processInstanceRepository; + this.processInstanceService = processInstanceService; + } + + public Page findAllProcessInstances(Predicate predicate, Pageable pageable) { + Page processInstances = processInstanceService.findAll(predicate, pageable); + return mapAllSubprocesses(processInstances, pageable); + } + + public Page findAllProcessInstancesWithVariables( + Predicate predicate, + List variableKeys, + Pageable pageable + ) { + Page processInstances = processInstanceService.findAllWithVariables( + predicate, + variableKeys, + pageable + ); + return mapAllSubprocesses(processInstances, pageable); + } + + public ProcessInstanceEntity findById(String processInstanceId) { + ProcessInstanceEntity processInstance = processInstanceService.findById(processInstanceId); + return processInstanceRepository.mapSubprocesses(processInstance); + } + + public Page searchProcessInstances( + ProcessInstanceSearchRequest searchRequest, + Pageable pageable + ) { + Page processInstances = processInstanceService.search(searchRequest, pageable); + return mapAllSubprocesses(processInstances, pageable); + } + + public Page searchSubprocesses( + String processInstanceId, + Predicate predicate, + Pageable pageable + ) { + Page processInstanceSubprocesses = processInstanceService.subprocesses( + processInstanceId, + predicate, + pageable + ); + return mapAllSubprocesses(processInstanceSubprocesses, pageable); + } + + public Page mapAllSubprocesses( + Page processInstances, + Pageable pageable + ) { + return processInstanceRepository.mapSubprocesses(processInstances, pageable); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/repos/CustomizedProcessInstanceRepositoryImplIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/repos/CustomizedProcessInstanceRepositoryImplIT.java new file mode 100644 index 00000000000..59408f44cd5 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/repos/CustomizedProcessInstanceRepositoryImplIT.java @@ -0,0 +1,147 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.activiti.cloud.services.query.repos; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.buildProcessInstanceEntity; +import static org.assertj.core.api.Assertions.assertThat; + +import jakarta.persistence.EntityManager; +import java.util.ArrayList; +import java.util.List; +import org.activiti.QueryRestTestApplication; +import org.activiti.cloud.services.query.app.repository.CustomizedProcessInstanceRepositoryImpl; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.test.context.TestPropertySource; +import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + classes = { QueryRestTestApplication.class }, + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@TestPropertySource("classpath:application-test.properties") +@Testcontainers +@Transactional +class CustomizedProcessInstanceRepositoryImplIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + private CustomizedProcessInstanceRepositoryImpl repository; + + @Autowired + private ProcessInstanceRepository processInstanceRepository; + + @Autowired + private EntityManager entityManager; + + @BeforeEach + void setUp() { + processInstanceRepository.deleteAll(); + } + + @Test + void testMapSubprocessesForPage() { + Pageable pageable = PageRequest.of(0, 10); + List processInstancesList = buildDefaultProcessInstances(3); + String parentId1 = processInstancesList.getFirst().getId(); + List subprocesses1 = buildDefaultProcessInstances(2); + setSubprocesses(subprocesses1, parentId1); + String parentId2 = processInstancesList.getLast().getId(); + List subprocesses2 = buildDefaultProcessInstances(3); + setSubprocesses(subprocesses2, parentId2); + + entityManager.flush(); + + Page processInstances = new PageImpl<>( + processInstancesList, + pageable, + processInstancesList.size() + ); + + Page result = repository.mapSubprocesses(processInstances, pageable); + + assertThat(result).isNotNull(); + assertThat(result.getTotalElements()).isEqualTo(3); + + ProcessInstanceEntity parentInstance1 = result + .getContent() + .stream() + .filter(instance -> instance.getId().equals(parentId1)) + .findFirst() + .orElse(null); + assertThat(parentInstance1).isNotNull(); + assertThat(parentInstance1.getSubprocesses()).hasSize(2); + + ProcessInstanceEntity parentInstance2 = result + .getContent() + .stream() + .filter(instance -> instance.getId().equals(parentId2)) + .findFirst() + .orElse(null); + assertThat(parentInstance2).isNotNull(); + assertThat(parentInstance2.getSubprocesses()).hasSize(3); + } + + @Test + void testMapSubprocessesForProcessInstance() { + List processInstances = buildDefaultProcessInstances(5); + List subprocesses = buildDefaultProcessInstances(2); + ProcessInstanceEntity entity = processInstances.getFirst(); + String parentId = entity.getId(); + setSubprocesses(subprocesses, parentId); + + ProcessInstanceEntity result = repository.mapSubprocesses(entity); + + assertThat(result).isNotNull(); + assertThat(result.getSubprocesses().stream().toList().getLast().getId()).isNotNull(); + } + + private List buildDefaultProcessInstances(int count) { + List entities = new ArrayList<>(); + for (int i = 1; i <= count; i++) { + entities.add(buildProcessInstanceEntity()); + } + processInstanceRepository.saveAll(entities); + return entities; + } + + private void setSubprocesses(List subprocesses, String parentId) { + for (ProcessInstanceEntity subprocess : subprocesses) { + subprocess.setParentId(parentId); + processInstanceRepository.save(subprocess); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperIT.java new file mode 100644 index 00000000000..7b98796df60 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperIT.java @@ -0,0 +1,191 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.buildProcessInstanceEntity; +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.createProcessVariables; +import static org.assertj.core.api.Assertions.assertThat; + +import com.querydsl.core.types.Predicate; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.activiti.api.process.model.ProcessInstance; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceAdminControllerHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { "spring.main.banner-mode=off", "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false" } +) +@TestPropertySource("classpath:application-test.properties") +@EnableAutoConfiguration +@Testcontainers +class ProcessInstanceAdminControllerHelperIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + ProcessInstanceAdminControllerHelper processInstanceAdminControllerHelper; + + @Autowired + ProcessInstanceRepository processInstanceRepository; + + @BeforeEach + void setUp() { + processInstanceRepository.deleteAll(); + } + + @Test + void shouldReturnAllProcessInstanceAdmin() { + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + processInstanceRepository.save(processInstanceEntity); + Predicate predicate = null; + int pageSize = 30; + Pageable pageable = getPageableSortedByLastModifiedDescending(pageSize); + + Page result = processInstanceAdminControllerHelper.findAllProcessInstanceAdmin( + predicate, + pageable + ); + + assertThat(result.getContent()).contains(processInstanceEntity); + + ProcessInstanceEntity returnedProcessInstance = verifyReturnedProcessInstanceEntity( + result, + processInstanceEntity + ); + + assertThat(returnedProcessInstance).isNotNull(); + assertThat(returnedProcessInstance.getSubprocesses()).isEmpty(); + } + + @Test + void shouldReturnAllProcessInstanceAdminWithSubprocess() { + ProcessInstanceEntity parentProcessInstance = buildProcessInstanceEntity(); + ProcessInstanceEntity subprocessInstance = buildSubprocessInstance(parentProcessInstance); + + processInstanceRepository.save(parentProcessInstance); + processInstanceRepository.save(subprocessInstance); + + Predicate predicate = null; + int pageSize = 30; + Pageable pageable = getPageableSortedByLastModifiedDescending(pageSize); + + Page result = processInstanceAdminControllerHelper.findAllProcessInstanceAdmin( + predicate, + pageable + ); + + assertThat(result.getContent()).contains(parentProcessInstance, subprocessInstance); + + ProcessInstanceEntity returnedParentProcessInstance = verifyReturnedProcessInstanceEntity( + result, + parentProcessInstance + ); + + assertThat(returnedParentProcessInstance).isNotNull(); + assertThat(returnedParentProcessInstance.getSubprocesses()) + .anyMatch(subprocess -> + subprocess.getId().equals(subprocessInstance.getId()) && + subprocess.getProcessDefinitionName().equals(subprocessInstance.getProcessDefinitionName()) + ); + } + + @Test + void shouldReturnAllProcessInstanceAdminWithVariables() { + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + processInstanceRepository.save(processInstanceEntity); + + Set variables = createProcessVariables(processInstanceEntity, 8); + List variableKeys = variables.stream().map(ProcessVariableEntity::getName).toList(); + Predicate predicate = null; + int pageSize = 30; + Pageable pageable = getPageableSortedByLastModifiedDescending(pageSize); + + Page result = processInstanceAdminControllerHelper.findAllProcessInstanceAdminWithVariables( + predicate, + variableKeys, + pageable + ); + + assertThat(result.getContent()).contains(processInstanceEntity); + } + + @Test + void shouldReturnProcessAdminById() { + ProcessInstanceEntity parentProcessInstance = buildProcessInstanceEntity(); + ProcessInstanceEntity subprocessInstance = buildSubprocessInstance(parentProcessInstance); + + processInstanceRepository.save(parentProcessInstance); + processInstanceRepository.save(subprocessInstance); + String processInstanceId = parentProcessInstance.getId(); + + ProcessInstanceEntity result = processInstanceAdminControllerHelper.findByIdProcessAdmin(processInstanceId); + + assertThat(result).isEqualTo(parentProcessInstance); + assertThat( + result + .getSubprocesses() + .stream() + .anyMatch(subprocess -> subprocess.getId().equals(subprocessInstance.getId())) + ) + .isTrue(); + } + + private ProcessInstanceEntity buildSubprocessInstance(ProcessInstanceEntity parentProcessInstance) { + ProcessInstanceEntity subprocessInstance = new ProcessInstanceEntity(); + subprocessInstance.setId(UUID.randomUUID().toString()); + subprocessInstance.setProcessDefinitionKey("mySubprocess"); + subprocessInstance.setProcessDefinitionName("subprocess"); + subprocessInstance.setStatus(ProcessInstance.ProcessInstanceStatus.RUNNING); + subprocessInstance.setParentId(parentProcessInstance.getId()); + return subprocessInstance; + } + + private ProcessInstanceEntity verifyReturnedProcessInstanceEntity( + Page result, + ProcessInstanceEntity parentProcessInstance + ) { + return result + .getContent() + .stream() + .filter(pi -> pi.getId().equals(parentProcessInstance.getId())) + .findFirst() + .orElse(null); + } + + private PageRequest getPageableSortedByLastModifiedDescending(int pageSize) { + return PageRequest.of(0, pageSize, Sort.by("lastModified").descending()); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperTest.java new file mode 100644 index 00000000000..8449a1d9a90 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerHelperTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +import com.querydsl.core.types.Predicate; +import java.util.Collections; +import java.util.List; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceAdminControllerHelper; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceControllerHelper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +@ExtendWith(MockitoExtension.class) +class ProcessInstanceAdminControllerHelperTest { + + @InjectMocks + private ProcessInstanceAdminControllerHelper processInstanceAdminControllerHelper; + + @Mock + private ProcessInstanceRepository processInstanceRepository; + + @Mock + private ProcessInstanceAdminService processInstanceAdminService; + + @Mock + private ProcessInstanceControllerHelper processInstanceControllerHelper; + + @Test + void findAllProcessInstanceAdmin_shouldReturnProcessInstances() { + //given + Predicate predicate = mock(Predicate.class); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceAdminService.findAll(predicate, pageable)).willReturn(pageResult); + given(processInstanceControllerHelper.mapAllSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceAdminControllerHelper.findAllProcessInstanceAdmin( + predicate, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } + + @Test + void findAllProcessInstanceAdminWithVariables_shouldReturnProcessInstances() { + //given + Predicate predicate = mock(Predicate.class); + List variableKeys = Collections.singletonList("var1"); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceAdminService.findAllWithVariables(predicate, variableKeys, pageable)) + .willReturn(pageResult); + given(processInstanceControllerHelper.mapAllSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceAdminControllerHelper.findAllProcessInstanceAdminWithVariables( + predicate, + variableKeys, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } + + @Test + void findByIdProcessAdmin_shouldReturnProcessInstance() { + //given + String processInstanceId = "1"; + ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); + given(processInstanceAdminService.findById(processInstanceId)).willReturn(processInstanceEntity); + given(processInstanceRepository.mapSubprocesses(processInstanceEntity)).willReturn(processInstanceEntity); + + //when + ProcessInstanceEntity result = processInstanceAdminControllerHelper.findByIdProcessAdmin(processInstanceId); + + //then + assertThat(result).isEqualTo(processInstanceEntity); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerIT.java new file mode 100644 index 00000000000..69b265afaec --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminControllerIT.java @@ -0,0 +1,207 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.buildProcessInstanceEntity; +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.createProcessVariables; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.querydsl.core.types.Predicate; +import jakarta.persistence.EntityManagerFactory; +import java.util.*; +import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; +import org.activiti.api.runtime.shared.security.SecurityManager; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.EntityFinder; +import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.security.TaskLookupRestrictionService; +import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; +import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.config.EnableSpringDataWebSupport; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; + +@WebMvcTest(ProcessInstanceAdminController.class) +@Import( + { QueryRestWebMvcAutoConfiguration.class, CommonModelAutoConfiguration.class, AlfrescoWebAutoConfiguration.class } +) +@EnableSpringDataWebSupport +@AutoConfigureMockMvc +@WithMockUser +@TestPropertySource( + locations = { "classpath:application-test.properties" }, + properties = "activiti.cloud.rest.max-items.enabled=true" +) +class ProcessInstanceAdminControllerIT { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private SecurityManager securityManager; + + @MockBean + private EntityFinder entityFinder; + + @MockBean + private SecurityPoliciesManager securityPoliciesManager; + + @MockBean + private ProcessDefinitionRepository processDefinitionRepository; + + @MockBean + private SecurityPoliciesProperties securityPoliciesProperties; + + @MockBean + private TaskLookupRestrictionService taskLookupRestrictionService; + + @MockBean + private TaskRepository taskRepository; + + @MockBean + private TaskControllerHelper taskControllerHelper; + + @MockBean + private VariableRepository processVariableRepository; + + @MockBean + private EntityManagerFactory entityManagerFactory; + + @MockBean + private ProcessInstanceAdminService processInstanceAdminService; + + @BeforeEach + void setUp() { + assertThat(entityManagerFactory).isNotNull(); + } + + @Test + void shouldReturnProcessInstancesWithoutVariableKeys() throws Exception { + //given + ProcessInstanceEntity parentProcessInstance = buildProcessInstanceEntity(); + + Page processInstancePage = new PageImpl<>( + Collections.singletonList(parentProcessInstance), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); + //when + mockMvc + .perform(get("/admin/v1/process-instances?skipCount=10&maxItems=10").accept(MediaType.APPLICATION_JSON)) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(parentProcessInstance.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(parentProcessInstance.getStatus().name())) + .andExpect( + jsonPath("$.list.entries[0].entry.processDefinitionId") + .value(parentProcessInstance.getProcessDefinitionId()) + ); + } + + @Test + void shouldReturnProcessInstancesWithVariableKeys() throws Exception { + //given + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + Set variables = createProcessVariables(processInstanceEntity, 6); + List variableKeys = variables.stream().map(ProcessVariableEntity::getName).toList(); + + Page processInstancePage = new PageImpl<>( + Collections.singletonList(processInstanceEntity), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceAdminService.findAllWithVariables(null, variableKeys, PageRequest.of(0, 10))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); + + //when + mockMvc + .perform( + get("/admin/v1/process-instances?variableKeys={variableKeys}&skipCount=10&maxItems=10", variableKeys) + .accept(MediaType.APPLICATION_JSON) + ) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(processInstanceEntity.getStatus().name())) + .andExpect(jsonPath("$.list.entries[0].entry.serviceName").value(processInstanceEntity.getServiceName())); + } + + @Test + void shouldReturnProcessInstanceById() throws Exception { + //given + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + String processInstanceId = processInstanceEntity.getId(); + given(processInstanceAdminService.findById(processInstanceId)).willReturn(processInstanceEntity); + given(processInstanceRepository.mapSubprocesses(processInstanceEntity)).willReturn(processInstanceEntity); + + //when + mockMvc + .perform( + get("/admin/v1/process-instances/{processInstanceId}", processInstanceId) + .accept(MediaType.APPLICATION_JSON) + ) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.entry.serviceName").value(processInstanceEntity.getServiceName())) + .andExpect(jsonPath("$.entry.serviceFullName").value(processInstanceEntity.getServiceFullName())); + } + + @Test + void shouldReturnProcessAppVersions() throws Exception { + //given + given(processInstanceAdminService.findAllAppVersions(any(Predicate.class))) + .willReturn(Collections.singleton("1.0")); + + //when + mockMvc + .perform(get("/admin/v1/process-instances/appVersions").accept(MediaType.APPLICATION_JSON)) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0]").value("1.0")); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperIT.java new file mode 100644 index 00000000000..7d11318ace6 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperIT.java @@ -0,0 +1,195 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.buildProcessInstanceEntity; +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.createProcessVariables; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import com.querydsl.core.types.Predicate; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.activiti.api.process.model.ProcessInstance; +import org.activiti.api.runtime.shared.security.SecurityManager; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceControllerHelper; +import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { "spring.main.banner-mode=off", "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false" } +) +@TestPropertySource("classpath:application-test.properties") +@EnableAutoConfiguration +@Testcontainers +@WithMockUser +class ProcessInstanceControllerHelperIT { + + private static final String TEST_USER = "testuser"; + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + private ProcessInstanceControllerHelper processInstanceControllerHelper; + + @Autowired + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private SecurityManager securityManager; + + @MockBean + private SecurityPoliciesManager securityPoliciesManager; + + @BeforeEach + void setUp() { + processInstanceRepository.deleteAll(); + } + + @Test + void shouldReturnAllProcessInstances() { + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + processInstanceEntity.setInitiator(TEST_USER); + processInstanceRepository.save(processInstanceEntity); + //given + given( + securityPoliciesManager.canRead( + processInstanceEntity.getProcessDefinitionKey(), + processInstanceEntity.getServiceName() + ) + ) + .willReturn(true); + given(securityManager.getAuthenticatedUserId()).willReturn(TEST_USER); + + Predicate predicate = null; + int pageSize = 30; + Pageable pageable = PageRequest.of(0, pageSize, Sort.by("lastModified").descending()); + + Page result = processInstanceControllerHelper.findAllProcessInstances( + predicate, + pageable + ); + + assertThat(result.getContent()).contains(processInstanceEntity); + + ProcessInstanceEntity returnedProcessInstance = verifyReturnedProcessInstanceEntity( + result, + processInstanceEntity + ); + + assertThat(returnedProcessInstance).isNotNull(); + assertThat(returnedProcessInstance.getSubprocesses()).isEmpty(); + } + + @Test + void shouldReturnAllProcessInstancesWithVariables() { + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + processInstanceEntity.setInitiator(TEST_USER); + processInstanceRepository.save(processInstanceEntity); + //given + given( + securityPoliciesManager.canRead( + processInstanceEntity.getProcessDefinitionKey(), + processInstanceEntity.getServiceName() + ) + ) + .willReturn(true); + given(securityManager.getAuthenticatedUserId()).willReturn(TEST_USER); + + Set variables = createProcessVariables(processInstanceEntity, 8); + List variableKeys = variables.stream().map(ProcessVariableEntity::getName).toList(); + Predicate predicate = null; + int pageSize = 30; + Pageable pageable = PageRequest.of(0, pageSize, Sort.by("lastModified").descending()); + + Page result = processInstanceControllerHelper.findAllProcessInstancesWithVariables( + predicate, + variableKeys, + pageable + ); + + assertThat(result.getContent()).contains(processInstanceEntity); + } + + @Test + void shouldReturnProcessInstanceById() { + ProcessInstanceEntity parentProcessInstance = buildProcessInstanceEntity(); + parentProcessInstance.setInitiator(TEST_USER); + processInstanceRepository.save(parentProcessInstance); + ProcessInstanceEntity subprocessInstance = buildSubprocessInstance(parentProcessInstance); + + processInstanceRepository.save(parentProcessInstance); + processInstanceRepository.save(subprocessInstance); + //given + given( + securityPoliciesManager.canRead( + parentProcessInstance.getProcessDefinitionKey(), + parentProcessInstance.getServiceName() + ) + ) + .willReturn(true); + given(securityManager.getAuthenticatedUserId()).willReturn(TEST_USER); + + String processInstanceId = parentProcessInstance.getId(); + + ProcessInstanceEntity result = processInstanceControllerHelper.findById(processInstanceId); + + assertThat(result).isEqualTo(parentProcessInstance); + } + + private ProcessInstanceEntity buildSubprocessInstance(ProcessInstanceEntity parentProcessInstance) { + ProcessInstanceEntity subprocessInstance = new ProcessInstanceEntity(); + subprocessInstance.setId(UUID.randomUUID().toString()); + subprocessInstance.setProcessDefinitionKey("mySubprocess"); + subprocessInstance.setProcessDefinitionName("subprocess"); + subprocessInstance.setStatus(ProcessInstance.ProcessInstanceStatus.RUNNING); + subprocessInstance.setParentId(parentProcessInstance.getId()); + return subprocessInstance; + } + + private ProcessInstanceEntity verifyReturnedProcessInstanceEntity( + Page result, + ProcessInstanceEntity parentProcessInstance + ) { + return result + .getContent() + .stream() + .filter(pi -> pi.getId().equals(parentProcessInstance.getId())) + .findFirst() + .orElse(null); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperTest.java new file mode 100644 index 00000000000..3c6e25477f3 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerHelperTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.createProcessInstanceSearchRequest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +import com.querydsl.core.types.Predicate; +import java.util.Collections; +import java.util.List; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.rest.helper.ProcessInstanceControllerHelper; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +@ExtendWith(MockitoExtension.class) +class ProcessInstanceControllerHelperTest { + + @InjectMocks + private ProcessInstanceControllerHelper processInstanceControllerHelper; + + @Mock + private ProcessInstanceRepository processInstanceRepository; + + @Mock + private ProcessInstanceService processInstanceService; + + @Test + void findAllProcessInstances_shouldReturnProcessInstances() { + //given + Predicate predicate = mock(Predicate.class); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceService.findAll(predicate, pageable)).willReturn(pageResult); + given(processInstanceRepository.mapSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceControllerHelper.findAllProcessInstances( + predicate, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } + + @Test + void findAllProcessInstancesWithVariables_shouldReturnProcessInstances() { + //given + Predicate predicate = mock(Predicate.class); + List variableKeys = Collections.singletonList("var1"); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceService.findAllWithVariables(predicate, variableKeys, pageable)).willReturn(pageResult); + given(processInstanceRepository.mapSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceControllerHelper.findAllProcessInstancesWithVariables( + predicate, + variableKeys, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } + + @Test + void findById_shouldReturnProcessInstance() { + //given + String processInstanceId = "1"; + ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); + given(processInstanceService.findById(processInstanceId)).willReturn(processInstanceEntity); + given(processInstanceRepository.mapSubprocesses(processInstanceEntity)).willReturn(processInstanceEntity); + + //when + ProcessInstanceEntity result = processInstanceControllerHelper.findById(processInstanceId); + + //then + assertThat(result).isEqualTo(processInstanceEntity); + } + + @Test + void searchProcessInstances_shouldReturnProcessInstances() { + //given + ProcessInstanceSearchRequest searchRequest = createProcessInstanceSearchRequest(); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceService.search(searchRequest, pageable)).willReturn(pageResult); + given(processInstanceRepository.mapSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceControllerHelper.searchProcessInstances( + searchRequest, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } + + @Test + void searchSubprocesses_shouldReturnSubprocesses() { + //given + String processInstanceId = "1"; + Predicate predicate = mock(Predicate.class); + Pageable pageable = PageRequest.of(0, 10); + Page pageResult = new PageImpl<>(Collections.singletonList(new ProcessInstanceEntity())); + given(processInstanceService.subprocesses(processInstanceId, predicate, pageable)).willReturn(pageResult); + given(processInstanceRepository.mapSubprocesses(pageResult, pageable)).willReturn(pageResult); + + //when + Page result = processInstanceControllerHelper.searchSubprocesses( + processInstanceId, + predicate, + pageable + ); + + //then + assertThat(result).isEqualTo(pageResult); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerIT.java new file mode 100644 index 00000000000..3a800279793 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceControllerIT.java @@ -0,0 +1,203 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.rest; + +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.buildProcessInstanceEntity; +import static org.activiti.cloud.services.query.util.ProcessInstanceTestUtils.createProcessVariables; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.querydsl.core.types.Predicate; +import jakarta.persistence.EntityManagerFactory; +import java.util.*; +import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; +import org.activiti.api.runtime.shared.security.SecurityManager; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.EntityFinder; +import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.security.ProcessInstanceRestrictionService; +import org.activiti.cloud.services.security.TaskLookupRestrictionService; +import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; +import org.activiti.core.common.spring.security.policies.SecurityPolicyAccess; +import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.domain.*; +import org.springframework.data.web.config.EnableSpringDataWebSupport; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; + +@WebMvcTest(ProcessInstanceController.class) +@Import( + { QueryRestWebMvcAutoConfiguration.class, CommonModelAutoConfiguration.class, AlfrescoWebAutoConfiguration.class } +) +@EnableSpringDataWebSupport +@AutoConfigureMockMvc +@WithMockUser +@TestPropertySource( + locations = { "classpath:application-test.properties" }, + properties = "activiti.cloud.rest.max-items.enabled=true" +) +class ProcessInstanceControllerIT { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private SecurityManager securityManager; + + @MockBean + private EntityFinder entityFinder; + + @MockBean + private SecurityPoliciesManager securityPoliciesManager; + + @MockBean + private ProcessDefinitionRepository processDefinitionRepository; + + @MockBean + private SecurityPoliciesProperties securityPoliciesProperties; + + @MockBean + private TaskLookupRestrictionService taskLookupRestrictionService; + + @MockBean + private ProcessInstanceRestrictionService processInstanceRestrictionService; + + @MockBean + private TaskRepository taskRepository; + + @MockBean + private TaskControllerHelper taskControllerHelper; + + @MockBean + private VariableRepository processVariableRepository; + + @MockBean + private EntityManagerFactory entityManagerFactory; + + @MockBean + private ProcessInstanceService processInstanceService; + + @BeforeEach + void setUp() { + assertThat(entityManagerFactory).isNotNull(); + } + + @Test + void shouldReturnProcessInstancesWithoutVariableKeys() throws Exception { + //given + Predicate restrictedPredicate = mock(Predicate.class); + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + Page processInstancePage = new PageImpl<>( + Collections.singletonList(processInstanceEntity), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceRestrictionService.restrictProcessInstanceQuery(any(), eq(SecurityPolicyAccess.READ))) + .willReturn(restrictedPredicate); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); + + //when + mockMvc + .perform(get("/v1/process-instances?skipCount=10&maxItems=10").accept(MediaType.APPLICATION_JSON)) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(processInstanceEntity.getStatus().name())) + .andExpect(jsonPath("$.list.entries[0].entry.serviceName").value(processInstanceEntity.getServiceName())); + } + + @Test + void shouldReturnProcessInstancesWithVariableKeys() throws Exception { + //given + Predicate restrictedPredicate = mock(Predicate.class); + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + Set variables = createProcessVariables(processInstanceEntity, 6); + List variableKeys = variables.stream().map(ProcessVariableEntity::getName).toList(); + List ids = Collections.singletonList(processInstanceEntity.getId()); + + Page processInstancePage = new PageImpl<>( + Collections.singletonList(processInstanceEntity), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceRestrictionService.restrictProcessInstanceQuery(any(), eq(SecurityPolicyAccess.READ))) + .willReturn(restrictedPredicate); + given(processInstanceRepository.findByIdIsIn(ids, Sort.unsorted())) + .willReturn(Collections.singletonList(processInstanceEntity)); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); + + //when + mockMvc + .perform( + get("/v1/process-instances?variableKeys={variableKeys}&skipCount=10&maxItems=10", variableKeys) + .accept(MediaType.APPLICATION_JSON) + ) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(processInstanceEntity.getStatus().name())) + .andExpect(jsonPath("$.list.entries[0].entry.serviceName").value(processInstanceEntity.getServiceName())); + } + + @Test + void shouldReturnProcessInstanceById() throws Exception { + //given + Predicate restrictedPredicate = mock(Predicate.class); + ProcessInstanceEntity processInstanceEntity = buildProcessInstanceEntity(); + String processInstanceId = processInstanceEntity.getId(); + + given(processInstanceRestrictionService.restrictProcessInstanceQuery(any(), eq(SecurityPolicyAccess.READ))) + .willReturn(restrictedPredicate); + given(processInstanceService.findById(processInstanceId)).willReturn(processInstanceEntity); + given(processInstanceRepository.mapSubprocesses(processInstanceEntity)).willReturn(processInstanceEntity); + + //when + mockMvc + .perform( + get("/v1/process-instances/{processInstanceId}", processInstanceId).accept(MediaType.APPLICATION_JSON) + ) + //then + .andExpect(status().isOk()) + .andExpect(jsonPath("$.entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.entry.status").value(processInstanceEntity.getStatus().name())); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java index 2a119daca71..11d358a1bee 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java @@ -19,6 +19,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.querydsl.core.types.Predicate; @@ -49,6 +50,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -56,6 +58,7 @@ import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(ProcessInstanceAdminController.class) @@ -65,7 +68,11 @@ @EnableSpringDataWebSupport @AutoConfigureMockMvc @WithMockUser -public class ProcessInstanceEntityAdminControllerIT { +@TestPropertySource( + locations = { "classpath:application-test.properties" }, + properties = "activiti.cloud.rest.max-items.enabled=true" +) +class ProcessInstanceEntityAdminControllerIT { @Autowired private MockMvc mockMvc; @@ -112,33 +119,52 @@ void setUp() { } @Test - public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { + void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given - given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) - .willReturn( - new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) - ); + ProcessInstanceEntity processInstanceEntity = buildDefaultProcessInstance(); + Page processInstancePage = new PageImpl<>( + Collections.singletonList(processInstanceEntity), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); //when mockMvc .perform(get("/admin/v1/process-instances?skipCount=10&maxItems=10").accept(MediaType.APPLICATION_JSON)) //then - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(processInstanceEntity.getStatus().name())) + .andExpect(jsonPath("$.list.entries[0].entry.serviceName").value(processInstanceEntity.getServiceName())); } @Test - public void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { + void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { //given + ProcessInstanceEntity parentProcessInstance = buildDefaultProcessInstance(); + Page processInstancePage = new PageImpl<>( + Collections.singletonList(parentProcessInstance), + PageRequest.of(1, 10), + 1 + ); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) - .willReturn( - new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) - ); + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); //when mockMvc .perform(get("/admin/v1/process-instances?page=1&size=10").accept(MediaTypes.HAL_JSON_VALUE)) //then - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.processInstances.[0].id").value(parentProcessInstance.getId())) + .andExpect( + jsonPath("$._embedded.processInstances[0].processDefinitionId") + .value(parentProcessInstance.getProcessDefinitionId()) + ); } private ProcessInstanceEntity buildDefaultProcessInstance() { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java index 04a4353190a..acf6aeb7d26 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java @@ -21,6 +21,7 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.querydsl.core.types.Predicate; @@ -53,6 +54,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -60,6 +62,7 @@ import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(ProcessInstanceController.class) @@ -69,7 +72,11 @@ @EnableSpringDataWebSupport @AutoConfigureMockMvc @WithMockUser -public class ProcessInstanceEntityControllerIT { +@TestPropertySource( + locations = { "classpath:application-test.properties" }, + properties = "activiti.cloud.rest.max-items.enabled=true" +) +class ProcessInstanceEntityControllerIT { @Autowired private MockMvc mockMvc; @@ -119,39 +126,57 @@ void setUp() { } @Test - public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { + void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given Predicate restrictedPredicate = mock(Predicate.class); + ProcessInstanceEntity processInstanceEntity = buildDefaultProcessInstance(); + Page processInstancePage = new PageImpl<>( + Collections.singletonList(processInstanceEntity), + PageRequest.of(1, 10), + 1 + ); given(processInstanceRestrictionService.restrictProcessInstanceQuery(any(), eq(SecurityPolicyAccess.READ))) .willReturn(restrictedPredicate); - given(processInstanceRepository.findAll(eq(restrictedPredicate), any(Pageable.class))) - .willReturn( - new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) - ); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); //when mockMvc .perform(get("/v1/process-instances?skipCount=10&maxItems=10").accept(MediaType.APPLICATION_JSON)) //then - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.list.entries[0].entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.list.entries[0].entry.status").value(processInstanceEntity.getStatus().name())) + .andExpect(jsonPath("$.list.entries[0].entry.serviceName").value(processInstanceEntity.getServiceName())); } @Test - public void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { + void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { //given Predicate restrictedPredicate = mock(Predicate.class); + ProcessInstanceEntity parentProcessInstance = buildDefaultProcessInstance(); + Page processInstancePage = new PageImpl<>( + Collections.singletonList(parentProcessInstance), + PageRequest.of(1, 10), + 1 + ); given(processInstanceRestrictionService.restrictProcessInstanceQuery(any(), eq(SecurityPolicyAccess.READ))) .willReturn(restrictedPredicate); - given(processInstanceRepository.findAll(eq(restrictedPredicate), any(Pageable.class))) - .willReturn( - new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) - ); + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) + .willReturn(processInstancePage); + given(processInstanceRepository.mapSubprocesses(any(), any(Pageable.class))).willReturn(processInstancePage); //when mockMvc .perform(get("/v1/process-instances?page=1&size=10").accept(MediaTypes.HAL_JSON_VALUE)) //then - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.processInstances.[0].id").value(parentProcessInstance.getId())) + .andExpect( + jsonPath("$._embedded.processInstances[0].processDefinitionId") + .value(parentProcessInstance.getProcessDefinitionId()) + ); } private ProcessInstanceEntity buildDefaultProcessInstance() { @@ -169,7 +194,7 @@ private ProcessInstanceEntity buildDefaultProcessInstance() { } @Test - public void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { + void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given ProcessInstanceEntity processInstanceEntity = buildDefaultProcessInstance(); processInstanceEntity.setInitiator("testuser"); @@ -183,6 +208,8 @@ public void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() th ) .willReturn(true); given(securityManager.getAuthenticatedUserId()).willReturn("testuser"); + given(processInstanceRepository.mapSubprocesses(any(ProcessInstanceEntity.class))) + .willReturn(processInstanceEntity); //when this.mockMvc.perform( @@ -190,6 +217,8 @@ public void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() th .accept(MediaType.APPLICATION_JSON_VALUE) ) //then - .andExpect(status().isOk()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.entry.id").value(processInstanceEntity.getId())) + .andExpect(jsonPath("$.entry.status").value(processInstanceEntity.getStatus().name())); } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceTestUtils.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceTestUtils.java new file mode 100644 index 00000000000..a26e4f2f9ec --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceTestUtils.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.cloud.services.query.util; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import org.activiti.api.process.model.ProcessInstance; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; + +public class ProcessInstanceTestUtils { + + private ProcessInstanceTestUtils() {} + + public static ProcessInstanceEntity buildProcessInstanceEntity() { + return new ProcessInstanceEntity( + "My-app", + "My-app", + "1", + null, + null, + UUID.randomUUID().toString(), + UUID.randomUUID().toString(), + ProcessInstance.ProcessInstanceStatus.RUNNING, + new Date() + ); + } + + public static Set createProcessVariables( + ProcessInstanceEntity processInstanceEntity, + int numberOfVariables + ) { + Set variables = new HashSet<>(); + + for (int i = 0; i < numberOfVariables; i++) { + ProcessVariableEntity processVariableEntity = new ProcessVariableEntity(); + processVariableEntity.setName("name" + i); + processVariableEntity.setValue("id"); + processVariableEntity.setProcessInstanceId(processInstanceEntity.getId()); + processVariableEntity.setProcessDefinitionKey(processInstanceEntity.getProcessDefinitionKey()); + processVariableEntity.setProcessInstance(processInstanceEntity); + variables.add(processVariableEntity); + } + return variables; + } + + public static ProcessInstanceSearchRequest createProcessInstanceSearchRequest() { + return new ProcessInstanceSearchRequest( + Set.of("My-app"), // processDefinitionKeys + Set.of("initiator"), // initiators + Set.of("1.0"), // appVersions + Set.of("My-app"), // appNames + Set.of(ProcessInstance.ProcessInstanceStatus.RUNNING), // statuses + null, // lastModifiedFrom + null, // lastModifiedTo + null, // startFrom + null, // startTo + null, // completedFrom + null, // completedTo + null, // suspendedFrom + null, // suspendedTo + null, // processVariableFilters + null, // processVariableKeys + null // sort + ); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json index b3d88058ddd..3bb38dce1be 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json +++ b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json @@ -69,8 +69,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -79,8 +79,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -174,8 +174,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -184,8 +184,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -199,12 +199,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } } } @@ -599,8 +599,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -609,8 +609,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -997,8 +997,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -1007,8 +1007,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -1339,8 +1339,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -1349,8 +1349,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -1444,8 +1444,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -1454,8 +1454,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -1762,8 +1762,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -1772,8 +1772,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -1787,12 +1787,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } } } @@ -2073,8 +2073,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -2083,8 +2083,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -2346,8 +2346,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -2356,8 +2356,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -2371,12 +2371,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_General" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_General" } } } @@ -2451,8 +2451,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -2461,8 +2461,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -2476,12 +2476,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } } } @@ -2876,8 +2876,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -2886,8 +2886,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -2994,8 +2994,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3004,8 +3004,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3068,8 +3068,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3078,8 +3078,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3142,8 +3142,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3152,8 +3152,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3222,8 +3222,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3232,8 +3232,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3546,8 +3546,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3556,8 +3556,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3571,12 +3571,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_ProcessVariables" } } } @@ -3620,8 +3620,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3630,8 +3630,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3645,12 +3645,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_General" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_General" } } } @@ -3745,8 +3745,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3755,8 +3755,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -3862,8 +3862,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -3872,8 +3872,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4177,8 +4177,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4187,8 +4187,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4202,12 +4202,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_General" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/ListResponseContentQueryCloudProcessInstance_General" } } } @@ -4251,8 +4251,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4261,8 +4261,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4405,8 +4405,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4415,8 +4415,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4479,8 +4479,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4489,8 +4489,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4590,8 +4590,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4600,8 +4600,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4708,8 +4708,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4718,8 +4718,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4782,8 +4782,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4792,8 +4792,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4856,8 +4856,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4866,8 +4866,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -4936,8 +4936,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -4946,8 +4946,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5037,8 +5037,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5047,8 +5047,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5111,8 +5111,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5121,8 +5121,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5185,8 +5185,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5195,8 +5195,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5259,8 +5259,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5269,8 +5269,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5284,12 +5284,12 @@ "content": { "application/hal+json": { "schema": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_General" } }, "application/json": { "schema": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_General" } } } @@ -5384,8 +5384,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5394,8 +5394,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5487,8 +5487,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5497,8 +5497,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5590,8 +5590,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5600,8 +5600,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5664,8 +5664,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5674,8 +5674,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -5934,8 +5934,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -5944,8 +5944,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -6101,8 +6101,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -6111,8 +6111,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -6175,8 +6175,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -6185,8 +6185,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -6286,8 +6286,8 @@ } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { @@ -6296,8 +6296,8 @@ } } }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { @@ -6339,12 +6339,12 @@ "title": "ActivitiErrorMessage", "type": "object", "properties": { - "message": { - "type": "string" - }, "code": { "type": "integer", "format": "int32" + }, + "message": { + "type": "string" } } }, @@ -6613,22 +6613,22 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" + "taskVariable": { + "type": "boolean" }, - "value": { - "type": "object" + "taskId": { + "type": "string" }, - "type": { + "processInstanceId": { "type": "string" }, - "taskId": { + "name": { "type": "string" }, - "taskVariable": { - "type": "boolean" + "value": { + "type": "object" }, - "processInstanceId": { + "type": { "type": "string" } } @@ -6695,6 +6695,16 @@ "title": "QueryCloudTask_ProcessVariables", "type": "object", "properties": { + "processVariables": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/CloudVariableInstance_ProcessVariables" + } + }, + "processDefinitionName": { + "type": "string" + }, "permissions": { "type": "array", "items": { @@ -6707,16 +6717,6 @@ ] } }, - "processDefinitionName": { - "type": "string" - }, - "processVariables": { - "uniqueItems": true, - "type": "array", - "items": { - "$ref": "#/components/schemas/CloudVariableInstance_ProcessVariables" - } - }, "appName": { "type": "string" }, @@ -6735,39 +6735,6 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "duration": { - "type": "integer", - "format": "int64" - }, - "standalone": { - "type": "boolean" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "formKey": { - "type": "string" - }, - "businessKey": { - "type": "string" - }, - "assignee": { - "type": "string" - }, "createdDate": { "type": "string", "format": "date-time" @@ -6783,7 +6750,13 @@ "completedBy": { "type": "string" }, - "description": { + "businessKey": { + "type": "string" + }, + "assignee": { + "type": "string" + }, + "formKey": { "type": "string" }, "status": { @@ -6797,9 +6770,19 @@ "DELETED" ] }, - "processInstanceId": { + "description": { + "type": "string" + }, + "parentTaskId": { + "type": "string" + }, + "taskDefinitionKey": { "type": "string" }, + "completedDate": { + "type": "string", + "format": "date-time" + }, "candidateUsers": { "type": "array", "items": { @@ -6815,15 +6798,32 @@ "processDefinitionId": { "type": "string" }, - "parentTaskId": { + "processInstanceId": { "type": "string" }, - "taskDefinitionKey": { + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "name": { "type": "string" }, - "completedDate": { - "type": "string", - "format": "date-time" + "priority": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "owner": { + "type": "string" + }, + "duration": { + "type": "integer", + "format": "int64" + }, + "standalone": { + "type": "boolean" } } }, @@ -6924,10 +6924,50 @@ } } }, - "CloudProcessInstance_ProcessVariables": { - "title": "CloudProcessInstance_ProcessVariables", + "EntriesResponseContentQueryCloudProcessInstance_ProcessVariables": { + "title": "EntriesResponseContentQueryCloudProcessInstance_ProcessVariables", + "type": "object", + "properties": { + "entries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_ProcessVariables" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" + } + } + }, + "EntryResponseContentQueryCloudProcessInstance_ProcessVariables": { + "title": "EntryResponseContentQueryCloudProcessInstance_ProcessVariables", + "type": "object", + "properties": { + "entry": { + "$ref": "#/components/schemas/QueryCloudProcessInstance_ProcessVariables" + } + } + }, + "ListResponseContentQueryCloudProcessInstance_ProcessVariables": { + "title": "ListResponseContentQueryCloudProcessInstance_ProcessVariables", + "type": "object", + "properties": { + "list": { + "$ref": "#/components/schemas/EntriesResponseContentQueryCloudProcessInstance_ProcessVariables" + } + } + }, + "QueryCloudProcessInstance_ProcessVariables": { + "title": "QueryCloudProcessInstance_ProcessVariables", "type": "object", "properties": { + "subprocesses": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/QueryCloudSubprocessInstance_ProcessVariables" + } + }, "appName": { "type": "string" }, @@ -6946,32 +6986,16 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" - }, - "id": { - "type": "string" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "processDefinitionName": { - "type": "string" + "startDate": { + "type": "string", + "format": "date-time" }, - "processDefinitionKey": { + "initiator": { "type": "string" }, "businessKey": { "type": "string" }, - "initiator": { - "type": "string" - }, - "startDate": { - "type": "string", - "format": "date-time" - }, "parentId": { "type": "string" }, @@ -6985,45 +7009,40 @@ "COMPLETED" ] }, - "processDefinitionId": { - "type": "string" - }, "completedDate": { "type": "string", "format": "date-time" - } - } - }, - "EntriesResponseContentCloudProcessInstance_ProcessVariables": { - "title": "EntriesResponseContentCloudProcessInstance_ProcessVariables", - "type": "object", - "properties": { - "entries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_ProcessVariables" - } }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" - } - } - }, - "EntryResponseContentCloudProcessInstance_ProcessVariables": { - "title": "EntryResponseContentCloudProcessInstance_ProcessVariables", - "type": "object", - "properties": { - "entry": { - "$ref": "#/components/schemas/CloudProcessInstance_ProcessVariables" + "processDefinitionId": { + "type": "string" + }, + "processDefinitionName": { + "type": "string" + }, + "processDefinitionKey": { + "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" } } }, - "ListResponseContentCloudProcessInstance_ProcessVariables": { - "title": "ListResponseContentCloudProcessInstance_ProcessVariables", + "QueryCloudSubprocessInstance_ProcessVariables": { + "title": "QueryCloudSubprocessInstance_ProcessVariables", "type": "object", "properties": { - "list": { - "$ref": "#/components/schemas/EntriesResponseContentCloudProcessInstance_ProcessVariables" + "id": { + "type": "string" + }, + "processDefinitionName": { + "type": "string" } } }, @@ -7095,22 +7114,22 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" + "taskVariable": { + "type": "boolean" }, - "value": { - "type": "object" + "taskId": { + "type": "string" }, - "type": { + "processInstanceId": { "type": "string" }, - "taskId": { + "name": { "type": "string" }, - "taskVariable": { - "type": "boolean" + "value": { + "type": "object" }, - "processInstanceId": { + "type": { "type": "string" } } @@ -7195,22 +7214,22 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" + "taskVariable": { + "type": "boolean" }, - "value": { - "type": "object" + "taskId": { + "type": "string" }, - "type": { + "processInstanceId": { "type": "string" }, - "taskId": { + "name": { "type": "string" }, - "taskVariable": { - "type": "boolean" + "value": { + "type": "object" }, - "processInstanceId": { + "type": { "type": "string" } } @@ -7228,6 +7247,16 @@ "title": "QueryCloudTask_General", "type": "object", "properties": { + "processVariables": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/CloudVariableInstance_General" + } + }, + "processDefinitionName": { + "type": "string" + }, "permissions": { "type": "array", "items": { @@ -7240,16 +7269,6 @@ ] } }, - "processDefinitionName": { - "type": "string" - }, - "processVariables": { - "uniqueItems": true, - "type": "array", - "items": { - "$ref": "#/components/schemas/CloudVariableInstance_General" - } - }, "appName": { "type": "string" }, @@ -7268,39 +7287,6 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "duration": { - "type": "integer", - "format": "int64" - }, - "standalone": { - "type": "boolean" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "formKey": { - "type": "string" - }, - "businessKey": { - "type": "string" - }, - "assignee": { - "type": "string" - }, "createdDate": { "type": "string", "format": "date-time" @@ -7316,7 +7302,13 @@ "completedBy": { "type": "string" }, - "description": { + "businessKey": { + "type": "string" + }, + "assignee": { + "type": "string" + }, + "formKey": { "type": "string" }, "status": { @@ -7330,9 +7322,19 @@ "DELETED" ] }, - "processInstanceId": { + "description": { "type": "string" }, + "parentTaskId": { + "type": "string" + }, + "taskDefinitionKey": { + "type": "string" + }, + "completedDate": { + "type": "string", + "format": "date-time" + }, "candidateUsers": { "type": "array", "items": { @@ -7348,22 +7350,55 @@ "processDefinitionId": { "type": "string" }, - "parentTaskId": { + "processInstanceId": { "type": "string" }, - "taskDefinitionKey": { + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "name": { "type": "string" }, - "completedDate": { - "type": "string", - "format": "date-time" + "priority": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "owner": { + "type": "string" + }, + "duration": { + "type": "integer", + "format": "int64" + }, + "standalone": { + "type": "boolean" } } }, - "CloudProcessInstance_General": { - "title": "CloudProcessInstance_General", + "EntryResponseContentQueryCloudProcessInstance_General": { + "title": "EntryResponseContentQueryCloudProcessInstance_General", "type": "object", "properties": { + "entry": { + "$ref": "#/components/schemas/QueryCloudProcessInstance_General" + } + } + }, + "QueryCloudProcessInstance_General": { + "title": "QueryCloudProcessInstance_General", + "type": "object", + "properties": { + "subprocesses": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/QueryCloudSubprocessInstance_General" + } + }, "appName": { "type": "string" }, @@ -7382,32 +7417,16 @@ "appVersion": { "type": "string" }, - "name": { - "type": "string" - }, - "id": { - "type": "string" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "processDefinitionName": { - "type": "string" + "startDate": { + "type": "string", + "format": "date-time" }, - "processDefinitionKey": { + "initiator": { "type": "string" }, "businessKey": { "type": "string" }, - "initiator": { - "type": "string" - }, - "startDate": { - "type": "string", - "format": "date-time" - }, "parentId": { "type": "string" }, @@ -7421,32 +7440,51 @@ "COMPLETED" ] }, - "processDefinitionId": { - "type": "string" - }, "completedDate": { "type": "string", "format": "date-time" + }, + "processDefinitionId": { + "type": "string" + }, + "processDefinitionName": { + "type": "string" + }, + "processDefinitionKey": { + "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" } } }, - "EntryResponseContentCloudProcessInstance_General": { - "title": "EntryResponseContentCloudProcessInstance_General", + "QueryCloudSubprocessInstance_General": { + "title": "QueryCloudSubprocessInstance_General", "type": "object", "properties": { - "entry": { - "$ref": "#/components/schemas/CloudProcessInstance_General" + "id": { + "type": "string" + }, + "processDefinitionName": { + "type": "string" } } }, - "EntriesResponseContentCloudProcessInstance_General": { - "title": "EntriesResponseContentCloudProcessInstance_General", + "EntriesResponseContentQueryCloudProcessInstance_General": { + "title": "EntriesResponseContentQueryCloudProcessInstance_General", "type": "object", "properties": { "entries": { "type": "array", "items": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudProcessInstance_General" } }, "pagination": { @@ -7454,12 +7492,12 @@ } } }, - "ListResponseContentCloudProcessInstance_General": { - "title": "ListResponseContentCloudProcessInstance_General", + "ListResponseContentQueryCloudProcessInstance_General": { + "title": "ListResponseContentQueryCloudProcessInstance_General", "type": "object", "properties": { "list": { - "$ref": "#/components/schemas/EntriesResponseContentCloudProcessInstance_General" + "$ref": "#/components/schemas/EntriesResponseContentQueryCloudProcessInstance_General" } } }, @@ -7510,6 +7548,15 @@ "appVersion": { "type": "string" }, + "formKey": { + "type": "string" + }, + "category": { + "type": "string" + }, + "description": { + "type": "string" + }, "name": { "type": "string" }, @@ -7522,15 +7569,6 @@ "version": { "type": "integer", "format": "int32" - }, - "formKey": { - "type": "string" - }, - "category": { - "type": "string" - }, - "description": { - "type": "string" } } }, @@ -7619,23 +7657,13 @@ "title": "CloudServiceTask", "type": "object", "properties": { - "id": { - "type": "string" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "processDefinitionKey": { + "businessKey": { "type": "string" }, "startedDate": { "type": "string", "format": "date-time" }, - "businessKey": { - "type": "string" - }, "status": { "type": "string", "enum": [ @@ -7645,14 +7673,24 @@ "ERROR" ] }, - "cancelledDate": { + "completedDate": { "type": "string", "format": "date-time" }, - "completedDate": { + "cancelledDate": { "type": "string", "format": "date-time" }, + "processDefinitionKey": { + "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, "appName": { "type": "string" }, @@ -7683,10 +7721,10 @@ "elementId": { "type": "string" }, - "processInstanceId": { + "processDefinitionId": { "type": "string" }, - "processDefinitionId": { + "processInstanceId": { "type": "string" } } @@ -7728,9 +7766,6 @@ "title": "CloudIntegrationContext", "type": "object", "properties": { - "errorMessage": { - "type": "string" - }, "requestDate": { "type": "string", "format": "date-time" @@ -7739,10 +7774,6 @@ "type": "string", "format": "date-time" }, - "errorDate": { - "type": "string", - "format": "date-time" - }, "errorCode": { "type": "string" }, @@ -7754,6 +7785,10 @@ "INTEGRATION_ERROR_RECEIVED" ] }, + "errorDate": { + "type": "string", + "format": "date-time" + }, "errorClassName": { "type": "string" }, @@ -7790,20 +7825,19 @@ } } }, - "id": { + "errorMessage": { "type": "string" }, - "rootProcessInstanceId": { + "appVersion": { "type": "string" }, - "parentProcessInstanceId": { + "businessKey": { "type": "string" }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" + "executionId": { + "type": "string" }, - "processDefinitionKey": { + "clientType": { "type": "string" }, "clientId": { @@ -7812,18 +7846,6 @@ "clientName": { "type": "string" }, - "appVersion": { - "type": "string" - }, - "businessKey": { - "type": "string" - }, - "clientType": { - "type": "string" - }, - "executionId": { - "type": "string" - }, "connectorType": { "type": "string" }, @@ -7839,10 +7861,26 @@ "type": "object" } }, + "processDefinitionId": { + "type": "string" + }, "processInstanceId": { "type": "string" }, - "processDefinitionId": { + "rootProcessInstanceId": { + "type": "string" + }, + "processDefinitionKey": { + "type": "string" + }, + "parentProcessInstanceId": { + "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, + "id": { "type": "string" }, "appName": { diff --git a/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java b/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java index 45891b4b847..730f3873c2d 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java +++ b/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java @@ -21,7 +21,7 @@ import org.activiti.api.runtime.model.impl.BPMNActivityImpl; import org.activiti.api.runtime.model.impl.BPMNSequenceFlowImpl; import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.impl.CloudProcessInstanceImpl; +import org.activiti.cloud.api.process.model.impl.QueryCloudProcessInstanceImpl; import org.activiti.cloud.api.process.model.impl.events.CloudBPMNActivityCompletedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudBPMNActivityStartedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCompletedEventImpl; @@ -115,8 +115,8 @@ private ProcessInstanceImpl buildProcessInstance(String name, String initiator) return completedProcess; } - private CloudProcessInstanceImpl buildSuspendedProcessInstance(String name) { - CloudProcessInstanceImpl suspendedProcess = new CloudProcessInstanceImpl(); + private QueryCloudProcessInstanceImpl buildSuspendedProcessInstance(String name) { + QueryCloudProcessInstanceImpl suspendedProcess = new QueryCloudProcessInstanceImpl(); suspendedProcess.setId(UUID.randomUUID().toString()); suspendedProcess.setInitiator("testuser"); suspendedProcess.setName(name); @@ -177,8 +177,8 @@ public ProcessInstanceImpl aCompletedProcessInstanceWithAppVersion(String name, return processInstance; } - public CloudProcessInstanceImpl aRunningProcessInstanceWithSuspendedDate(String name, Date suspendedDate) { - CloudProcessInstanceImpl suspendedProcess = buildSuspendedProcessInstance(name); + public QueryCloudProcessInstanceImpl aRunningProcessInstanceWithSuspendedDate(String name, Date suspendedDate) { + QueryCloudProcessInstanceImpl suspendedProcess = buildSuspendedProcessInstance(name); suspendedProcess.setSuspendedDate(suspendedDate); eventsAggregator.addEvents( new CloudProcessCreatedEventImpl(suspendedProcess),