Skip to content

Commit

Permalink
AAE-28451 Add Subproceses to Process Instance (#1617)
Browse files Browse the repository at this point in the history
* AAE-28451 Add Subprocesses to process instance response for Process Admin and Workspace

---------

Co-authored-by: shsahahyland <[email protected]>
Co-authored-by: Riccardo Grandi <[email protected]>
Co-authored-by: Tommaso D'Alessandro <[email protected]>
  • Loading branch information
4 people authored Dec 5, 2024
1 parent b6f3298 commit 8678cfd
Show file tree
Hide file tree
Showing 29 changed files with 2,635 additions and 510 deletions.
Original file line number Diff line number Diff line change
@@ -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<QueryCloudSubprocessInstance> subprocesses;

@Override
public Set<QueryCloudSubprocessInstance> getSubprocesses() {
return subprocesses;
}

@Override
public void setSubprocesses(Set<QueryCloudSubprocessInstance> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
@@ -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<QueryCloudSubprocessInstance> getSubprocesses();

void setSubprocesses(Set<QueryCloudSubprocessInstance> subprocesses);
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -74,7 +75,7 @@
),
}
)
public class ProcessInstanceEntity extends ActivitiEntityMetadata implements CloudProcessInstance {
public class ProcessInstanceEntity extends ActivitiEntityMetadata implements QueryCloudProcessInstance {

@Id
private String id;
Expand Down Expand Up @@ -221,6 +222,9 @@ public class ProcessInstanceEntity extends ActivitiEntityMetadata implements Clo

private String parentId;

@Transient
private Set<QueryCloudSubprocessInstance> subprocesses;

public ProcessInstanceEntity() {}

public ProcessInstanceEntity(
Expand Down Expand Up @@ -510,4 +514,13 @@ public boolean equals(Object obj) {

return id != null && Objects.equals(id, other.id);
}

@Override
public Set<QueryCloudSubprocessInstance> getSubprocesses() {
return subprocesses;
}

public void setSubprocesses(Set<QueryCloudSubprocessInstance> subprocesses) {
this.subprocesses = subprocesses;
}
}
Original file line number Diff line number Diff line change
@@ -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<ProcessInstanceEntity> mapSubprocesses(Page<ProcessInstanceEntity> processInstances, Pageable pageable);

ProcessInstanceEntity mapSubprocesses(ProcessInstanceEntity processInstance);
}
Original file line number Diff line number Diff line change
@@ -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<ProcessInstanceEntity> mapSubprocesses(
Page<ProcessInstanceEntity> processInstances,
Pageable pageable
) {
List<String> parentIds = getParentIds(processInstances);

Page<ProcessInstanceEntity> subprocesses = findSubprocessesByParentIds(parentIds, pageable);

Map<String, Set<QueryCloudSubprocessInstance>> subprocessMap = groupSubprocesses(subprocesses);

setSubprocesses(processInstances, subprocessMap);

return processInstances;
}

@Override
public ProcessInstanceEntity mapSubprocesses(ProcessInstanceEntity processInstance) {
List<ProcessInstanceEntity> subprocesses = findSubprocessesByParentId(processInstance.getId());

if (subprocesses == null || subprocesses.isEmpty()) {
processInstance.setSubprocesses(new HashSet<>());
return processInstance;
}

Set<QueryCloudSubprocessInstance> 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<String> getParentIds(Page<ProcessInstanceEntity> processInstances) {
return processInstances.getContent().stream().map(ProcessInstanceEntity::getId).toList();
}

public Map<String, Set<QueryCloudSubprocessInstance>> groupSubprocesses(Page<ProcessInstanceEntity> subprocesses) {
return subprocesses
.getContent()
.stream()
.collect(
Collectors.groupingBy(
ProcessInstanceEntity::getParentId,
Collectors.mapping(this::getQueryCloudSubprocessInstance, Collectors.toSet())
)
);
}

public void setSubprocesses(
Page<ProcessInstanceEntity> processInstances,
Map<String, Set<QueryCloudSubprocessInstance>> subprocessMap
) {
processInstances
.getContent()
.forEach(processInstance -> {
Set<QueryCloudSubprocessInstance> subprocessSet = subprocessMap.getOrDefault(
processInstance.getId(),
Set.of()
);
processInstance.setSubprocesses(subprocessSet);
});
}

public Page<ProcessInstanceEntity> findSubprocessesByParentIds(List<String> parentIds, Pageable pageable) {
QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity;

Querydsl querydsl = getQuerydsl();

JPQLQuery<ProcessInstanceEntity> subprocessQuery = queryFactory
.selectFrom(processInstanceEntity)
.where(processInstanceEntity.parentId.in(parentIds));

long totalElements = subprocessQuery.fetchCount();

assert querydsl != null;
List<ProcessInstanceEntity> subprocesses = querydsl.applyPagination(pageable, subprocessQuery).fetch();

return PageableExecutionUtils.getPage(subprocesses, pageable, () -> totalElements);
}

public List<ProcessInstanceEntity> findSubprocessesByParentId(String parentId) {
QProcessInstanceEntity processInstanceEntity = QProcessInstanceEntity.processInstanceEntity;

return queryFactory
.selectFrom(processInstanceEntity)
.where(processInstanceEntity.parentId.eq(parentId))
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public interface ProcessInstanceRepository
JpaSpecificationExecutor<ProcessInstanceEntity>,
QuerydslPredicateExecutor<ProcessInstanceEntity>,
QuerydslBinderCustomizer<QProcessInstanceEntity>,
CustomizedProcessInstanceRepository,
CrudRepository<ProcessInstanceEntity, String> {
@Override
default void customize(QuerydslBindings bindings, QProcessInstanceEntity root) {
Expand Down
Loading

0 comments on commit 8678cfd

Please sign in to comment.