diff --git a/openbas-api/src/main/java/io/openbas/rest/atomic_testing/AtomicTestingApi.java b/openbas-api/src/main/java/io/openbas/rest/atomic_testing/AtomicTestingApi.java index 0ab17d6af9..99a79ba5ce 100644 --- a/openbas-api/src/main/java/io/openbas/rest/atomic_testing/AtomicTestingApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/atomic_testing/AtomicTestingApi.java @@ -1,5 +1,6 @@ package io.openbas.rest.atomic_testing; +import io.openbas.aop.LogExecutionTime; import io.openbas.database.model.Inject; import io.openbas.database.model.InjectExpectation; import io.openbas.inject_expectation.InjectExpectationService; @@ -30,6 +31,7 @@ public class AtomicTestingApi extends RestBehavior { private final AtomicTestingService atomicTestingService; private final InjectExpectationService injectExpectationService; + @LogExecutionTime @PostMapping("/search") @Transactional(readOnly = true) public Page findAllAtomicTestings( @@ -37,6 +39,7 @@ public Page findAllAtomicTestings( return atomicTestingService.findAllAtomicTestings(searchPaginationInput); } + @LogExecutionTime @GetMapping("/{injectId}") public InjectResultDTO findAtomicTesting(@PathVariable String injectId) { return atomicTestingService.findById(injectId); diff --git a/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java b/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java index 356a9c53f7..523bb90cc4 100644 --- a/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java +++ b/openbas-api/src/main/java/io/openbas/service/AtomicTestingService.java @@ -7,7 +7,6 @@ import static io.openbas.helper.StreamHelper.iterableToSet; import static io.openbas.utils.AtomicTestingUtils.*; import static io.openbas.utils.JpaUtils.createJoinArrayAggOnId; -import static io.openbas.utils.JpaUtils.createLeftJoin; import static io.openbas.utils.StringUtils.duplicateString; import static io.openbas.utils.pagination.PaginationUtils.buildPaginationCriteriaBuilder; import static io.openbas.utils.pagination.SortUtilsCriteriaBuilder.toSortCriteriaBuilder; @@ -299,6 +298,8 @@ public void deleteAtomicTesting(String injectId) { public Page findAllAtomicTestings( @NotNull final SearchPaginationInput searchPaginationInput) { + Map> joinMap = new HashMap<>(); + Specification customSpec = Specification.where( (root, query, cb) -> { @@ -312,20 +313,25 @@ public Page findAllAtomicTestings( Specification specificationCount, Pageable pageable) -> this.atomicTestings( - customSpec.and(specification), customSpec.and(specificationCount), pageable), + customSpec.and(specification), + customSpec.and(specificationCount), + pageable, + joinMap), searchPaginationInput, - Inject.class); + Inject.class, + joinMap); } public Page atomicTestings( Specification specification, Specification specificationCount, - Pageable pageable) { + Pageable pageable, + Map> joinMap) { CriteriaBuilder cb = this.entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createTupleQuery(); Root injectRoot = cq.from(Inject.class); - selectForAtomicTesting(cb, cq, injectRoot); + selectForAtomicTesting(cb, cq, injectRoot, joinMap); // -- Text Search and Filters -- if (specification != null) { @@ -399,13 +405,30 @@ public Page atomicTestings( } private void selectForAtomicTesting( - CriteriaBuilder cb, CriteriaQuery cq, Root injectRoot) { + CriteriaBuilder cb, + CriteriaQuery cq, + Root injectRoot, + Map> joinMap) { // Joins - Join injectorContractJoin = - createLeftJoin(injectRoot, "injectorContract"); - Join injectorJoin = - injectorContractJoin.join("injector", JoinType.LEFT); - Join injectStatusJoin = createLeftJoin(injectRoot, "status"); + Join injectorContractJoin = injectRoot.join("injectorContract", JoinType.LEFT); + joinMap.put("injectorContract", injectorContractJoin); + + Join injectorJoin = injectorContractJoin.join("injector", JoinType.LEFT); + joinMap.put("injector", injectorJoin); + + // Subquery for InjectStatus + Subquery statusSubquery = cq.subquery(Tuple.class); + Root statusRoot = statusSubquery.from(InjectStatus.class); + Subquery dateSubquery = cq.subquery(Tuple.class); + Root dateRoot = dateSubquery.from(InjectStatus.class); + + statusSubquery + .select(statusRoot.get("name")) + .where(cb.equal(statusRoot.get("inject").get("id"), injectRoot.get("id"))); + dateSubquery + .select(dateRoot.get("trackingSentDate")) + .where(cb.equal(dateRoot.get("inject").get("id"), injectRoot.get("id"))); + // Array aggregations Expression injectExpectationIdsExpression = createJoinArrayAggOnId(cb, injectRoot, EXPECTATIONS); @@ -421,7 +444,15 @@ private void selectForAtomicTesting( injectRoot.get("updatedAt").alias("inject_updated_at"), injectorJoin.get("type").alias("inject_type"), injectorContractJoin.alias("inject_injector_contract"), - injectStatusJoin.alias("inject_status"), + cb.selectCase() + .when(cb.exists(statusSubquery), statusSubquery.select(statusRoot.get("name"))) + .otherwise(cb.nullLiteral(ExecutionStatus.class)) + .alias("inject_status"), + cb.selectCase() + .when( + cb.exists(dateSubquery), dateSubquery.select(dateRoot.get("trackingSentDate"))) + .otherwise(cb.nullLiteral(Instant.class)) + .alias("tracking_sent_date"), injectExpectationIdsExpression.alias("inject_expectations"), teamIdsExpression.alias("inject_teams"), assetIdsExpression.alias("inject_assets"), @@ -431,27 +462,32 @@ private void selectForAtomicTesting( // GROUP BY cq.groupBy( Arrays.asList( - injectRoot.get("id"), - injectorContractJoin.get("id"), - injectorJoin.get("id"), - injectStatusJoin.get("id"))); + injectRoot.get("id"), injectorContractJoin.get("id"), injectorJoin.get("id"))); } private List execAtomicTesting(TypedQuery query) { return query.getResultList().stream() .map( - tuple -> - new AtomicTestingOutput( - tuple.get("inject_id", String.class), - tuple.get("inject_title", String.class), - tuple.get("inject_updated_at", Instant.class), - tuple.get("inject_type", String.class), - tuple.get("inject_injector_contract", InjectorContract.class), - tuple.get("inject_status", InjectStatus.class), - tuple.get("inject_expectations", String[].class), - tuple.get("inject_teams", String[].class), - tuple.get("inject_assets", String[].class), - tuple.get("inject_asset_groups", String[].class))) + tuple -> { + InjectStatus injectStatus = null; + ExecutionStatus status = tuple.get("inject_status", ExecutionStatus.class); + if (status != null) { + injectStatus = new InjectStatus(); + injectStatus.setName(status); + injectStatus.setTrackingSentDate(tuple.get("tracking_sent_date", Instant.class)); + } + return new AtomicTestingOutput( + tuple.get("inject_id", String.class), + tuple.get("inject_title", String.class), + tuple.get("inject_updated_at", Instant.class), + tuple.get("inject_type", String.class), + tuple.get("inject_injector_contract", InjectorContract.class), + injectStatus, + tuple.get("inject_expectations", String[].class), + tuple.get("inject_teams", String[].class), + tuple.get("inject_assets", String[].class), + tuple.get("inject_asset_groups", String[].class)); + }) .toList(); }