Skip to content

Commit ad05e37

Browse files
authored
Merge pull request #47 from Breeding-Insight/feature/BI-2476
BI-2476 Create Single and Batch Delete End Points for Germplasm
2 parents 6760fe6 + b13a93d commit ad05e37

13 files changed

+1078
-24
lines changed

src/main/java/io/swagger/api/germ/GermplasmApi.java

+16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import io.swagger.model.BrAPIResponse;
99
import io.swagger.model.Model202AcceptedSearchResponse;
10+
import io.swagger.model.core.ListsListResponse;
11+
import io.swagger.model.core.ListsSingleResponse;
1012
import io.swagger.model.germ.GermplasmListResponse;
1113
import io.swagger.model.germ.GermplasmMCPDResponse;
1214
import io.swagger.model.germ.GermplasmNewRequest;
@@ -45,6 +47,20 @@ ResponseEntity<GermplasmSingleResponse> germplasmGermplasmDbIdGet(
4547
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
4648
throws BrAPIServerException;
4749

50+
@ApiOperation(value = "Delete an existing germplasm", nickname = "germplasmGermplasmDbIdDelete", notes = "Delete an existing germplasm", response = GermplasmSingleResponse.class, authorizations = {
51+
@Authorization(value = "AuthorizationToken") }, tags = { "Germplasm", })
52+
@ApiResponses(value = { @ApiResponse(code = 204, message = "OK", response = GermplasmSingleResponse.class),
53+
@ApiResponse(code = 400, message = "Bad Request", response = String.class),
54+
@ApiResponse(code = 401, message = "Unauthorized", response = String.class),
55+
@ApiResponse(code = 403, message = "Forbidden", response = String.class),
56+
@ApiResponse(code = 404, message = "Not Found", response = String.class) })
57+
@RequestMapping(value = "/germplasm/{germplasmDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
58+
ResponseEntity<GermplasmSingleResponse> germplasmGermplasmDbIdDelete(
59+
@ApiParam(value = "The unique ID of this germplasm", required = true) @PathVariable("germplasmDbId") String germplasmDbId,
60+
@ApiParam(value = "hardDelete") @Valid @RequestParam(value = "hardDelete", defaultValue = "false", required = false) boolean hardDelete,
61+
@ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization)
62+
throws BrAPIServerException;
63+
4864
@ApiOperation(value = "Get the details of a specific Germplasm in MCPD format", nickname = "germplasmGermplasmDbIdMcpdGet", notes = "Get all MCPD details of a germplasm <a target=\"_blank\" href=\"https://www.bioversityInternational.org/fileadmin/user_upload/online_library/publications/pdfs/FAOBIOVERSITY_MULTI-CROP_PASSPORT_DESCRIPTORS_V.2.1_2015_2020.pdf\"> MCPD v2.1 spec can be found here </a> Implementation Notes - When the MCPD spec identifies a field which can have multiple values returned, the JSON response should be an array instead of a semi-colon separated string.", response = GermplasmMCPDResponse.class, authorizations = {
4965
@Authorization(value = "AuthorizationToken") }, tags = { "Germplasm", })
5066
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = GermplasmMCPDResponse.class),

src/main/java/org/brapi/test/BrAPITestServer/controller/germ/GermplasmApiController.java

+22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.swagger.model.BrAPIResponse;
44
import io.swagger.model.Metadata;
5+
import io.swagger.model.core.ListsSingleResponse;
56
import io.swagger.model.germ.Germplasm;
67
import io.swagger.model.germ.GermplasmListResponse;
78
import io.swagger.model.germ.GermplasmListResponseResult;
@@ -16,6 +17,7 @@
1617
import io.swagger.model.germ.GermplasmProgenyResponse;
1718
import io.swagger.api.germ.GermplasmApi;
1819

20+
import jakarta.validation.Valid;
1921
import org.brapi.test.BrAPITestServer.controller.core.BrAPIController;
2022
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
2123
import org.brapi.test.BrAPITestServer.model.entity.SearchRequestEntity;
@@ -72,6 +74,26 @@ public ResponseEntity<GermplasmSingleResponse> germplasmGermplasmDbIdGet(
7274
return responseOK(new GermplasmSingleResponse(), data);
7375
}
7476

77+
@CrossOrigin
78+
@Override
79+
public ResponseEntity<GermplasmSingleResponse> germplasmGermplasmDbIdDelete(
80+
@PathVariable("germplasmDbId") String germplasmDbId,
81+
@Valid @RequestParam(value = "hardDelete", defaultValue = "false" ,required = false) boolean hardDelete,
82+
@RequestHeader(value = "Authorization", required = false) String authorization) throws BrAPIServerException {
83+
84+
log.debug("Request: " + request.getRequestURI());
85+
validateSecurityContext(request, "ROLE_USER");
86+
validateAcceptHeader(request);
87+
88+
if (hardDelete) {
89+
germplasmService.deleteGermplasm(germplasmDbId);
90+
return responseNoContent();
91+
}
92+
93+
germplasmService.softDeleteGermplasm(germplasmDbId);
94+
return responseNoContent();
95+
}
96+
7597
@CrossOrigin
7698
@Override
7799
public ResponseEntity<GermplasmMCPDResponse> germplasmGermplasmDbIdMcpdGet(

src/main/java/org/brapi/test/BrAPITestServer/factory/germ/GermplasmComponent.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ public List<String> collectDbIds(List<Germplasm> entities) {
4040

4141
@Override
4242
public void deleteBatchDeleteData(List<String> dbIds) {
43-
43+
germplasmService.deleteGermplasmBatch(dbIds);
4444
}
4545

4646
@Override
4747
public void softDeleteBatchDeleteData(List<String> dbIds) {
48-
48+
germplasmService.softDeleteGermplasmBatch(dbIds);
4949
}
5050
}

src/main/java/org/brapi/test/BrAPITestServer/model/entity/germ/GermplasmEntity.java

+8
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
import io.swagger.model.germ.GermplasmMCPD.AcquisitionSourceCodeEnum;
1818
import io.swagger.model.germ.GermplasmMCPD.MlsStatusEnum;
1919
import io.swagger.model.germ.GermplasmStorageTypesEnum;
20+
import org.hibernate.annotations.Where;
2021

2122
@Entity
2223
@Table(name = "germplasm")
24+
@Where(clause = "soft_deleted = false")
2325
public class GermplasmEntity extends BrAPIPrimaryEntity {
2426
@Column
2527
private String accessionNumber;
@@ -84,6 +86,8 @@ public class GermplasmEntity extends BrAPIPrimaryEntity {
8486
private List<ObservationUnitEntity> observationUnits;
8587
@ElementCollection
8688
private List<GermplasmStorageTypesEnum> typeOfGermplasmStorageCode;
89+
@Column(name = "soft_deleted")
90+
private boolean softDeleted;
8791

8892
public GermplasmInstituteEntity getHostInstitute() {
8993
if (getInstitutes() != null) {
@@ -352,4 +356,8 @@ public void setTypeOfGermplasmStorageCode(List<GermplasmStorageTypesEnum> typeOf
352356
this.typeOfGermplasmStorageCode = typeOfGermplasmStorageCode;
353357
}
354358

359+
public boolean getSoftDeleted() { return softDeleted; }
360+
361+
public void setSoftDeleted(boolean sofDeleted) { this.softDeleted = sofDeleted; }
362+
355363
}

src/main/java/org/brapi/test/BrAPITestServer/model/entity/germ/PedigreeEdgeEntity.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class PedigreeEdgeEntity extends BrAPIPrimaryEntity{
1212
@ManyToOne(fetch = FetchType.LAZY)
1313
private PedigreeNodeEntity thisNode;
1414
@ManyToOne(fetch = FetchType.LAZY)
15-
private PedigreeNodeEntity conncetedNode;
15+
private PedigreeNodeEntity connectedNode;
1616
@Column
1717
private ParentType parentType;
1818
@Column
@@ -31,11 +31,11 @@ public EdgeType getEdgeType() {
3131
public void setEdgeType(EdgeType edgeType) {
3232
this.edgeType = edgeType;
3333
}
34-
public PedigreeNodeEntity getConncetedNode() {
35-
return conncetedNode;
34+
public PedigreeNodeEntity getConnectedNode() {
35+
return connectedNode;
3636
}
37-
public void setConncetedNode(PedigreeNodeEntity conncetedNode) {
38-
this.conncetedNode = conncetedNode;
37+
public void setConnectedNode(PedigreeNodeEntity connectedNode) {
38+
this.connectedNode = connectedNode;
3939
}
4040
public ParentType getParentType() {
4141
return parentType;

src/main/java/org/brapi/test/BrAPITestServer/model/entity/germ/PedigreeNodeEntity.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public List<PedigreeEdgeEntity> getParentEdges() {
9494
public List<PedigreeNodeEntity> getParentNodes() {
9595
return edges.stream().filter(e -> {
9696
return e.getEdgeType() == EdgeType.parent;
97-
}).map(edge -> edge.getConncetedNode()).collect(Collectors.toList());
97+
}).map(edge -> edge.getConnectedNode()).collect(Collectors.toList());
9898
}
9999

100100
public List<PedigreeEdgeEntity> getProgenyEdges() {
@@ -106,13 +106,13 @@ public List<PedigreeEdgeEntity> getProgenyEdges() {
106106
public List<PedigreeNodeEntity> getProgenyNodes() {
107107
return edges.stream().filter(e -> {
108108
return e.getEdgeType() == EdgeType.child;
109-
}).map(edge -> edge.getConncetedNode()).collect(Collectors.toList());
109+
}).map(edge -> edge.getConnectedNode()).collect(Collectors.toList());
110110
}
111111

112112
public void addParent(PedigreeNodeEntity node, ParentType type) {
113113
PedigreeEdgeEntity edge = new PedigreeEdgeEntity();
114114
edge.setThisNode(this);
115-
edge.setConncetedNode(node);
115+
edge.setConnectedNode(node);
116116
edge.setParentType(type);
117117
edge.setEdgeType(EdgeType.parent);
118118
if(edges == null)
@@ -123,7 +123,7 @@ public void addParent(PedigreeNodeEntity node, ParentType type) {
123123
public void addProgeny(PedigreeNodeEntity node, ParentType type) {
124124
PedigreeEdgeEntity edge = new PedigreeEdgeEntity();
125125
edge.setThisNode(this);
126-
edge.setConncetedNode(node);
126+
edge.setConnectedNode(node);
127127
edge.setParentType(type);
128128
edge.setEdgeType(EdgeType.child);
129129
if(edges == null)

src/main/java/org/brapi/test/BrAPITestServer/repository/germ/GermplasmRepository.java

+14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@
22

33
import org.brapi.test.BrAPITestServer.model.entity.germ.GermplasmEntity;
44
import org.brapi.test.BrAPITestServer.repository.BrAPIRepository;
5+
import org.springframework.data.jpa.repository.Modifying;
6+
import org.springframework.data.jpa.repository.Query;
7+
import org.springframework.data.repository.query.Param;
8+
import org.springframework.transaction.annotation.Transactional;
9+
10+
import java.util.List;
511

612
public interface GermplasmRepository extends BrAPIRepository<GermplasmEntity, String> {
13+
@Modifying
14+
@Transactional
15+
@Query("UPDATE GermplasmEntity g SET g.softDeleted = :softDeleted WHERE g.id = :germplasmId")
16+
int updateSoftDeletedStatus(@Param("germplasmId") String listId, @Param("softDeleted") boolean softDeleted);
717

18+
@Modifying
19+
@Transactional
20+
@Query("UPDATE GermplasmEntity g SET g.softDeleted = :softDeleted WHERE g.id IN :germplasmIds")
21+
int updateSoftDeletedStatusBatch(@Param("germplasmIds") List<String> germplasmIds, @Param("softDeleted") boolean softDeleted);
822
}

src/main/java/org/brapi/test/BrAPITestServer/repository/germ/PedigreeRepositoryCustomImpl.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public class PedigreeRepositoryCustomImpl implements PedigreeRepositoryCustom {
1717
public List<PedigreeNodeEntity> findPedigreeSiblings(PedigreeNodeEntity sourceNode) {
1818
String siblingSearchSQL = "select distinct siblingNode from PedigreeNodeEntity siblingNode "
1919
+ "join siblingNode.edges parentEdge "
20-
+ "join parentEdge.conncetedNode.edges childEdge "
21-
+ "join childEdge.conncetedNode sourceNode "
22-
+ "where sourceNode = :sourceId and parentEdge.edgeType = 0 and childEdge.edgeType = 1 and siblingNode.id != childEdge.conncetedNode.id";
20+
+ "join parentEdge.connectedNode.edges childEdge "
21+
+ "join childEdge.connectedNode sourceNode "
22+
+ "where sourceNode = :sourceId and parentEdge.edgeType = 0 and childEdge.edgeType = 1 and siblingNode.id != childEdge.connectedNode.id";
2323

2424
TypedQuery<PedigreeNodeEntity> query = em.createQuery(siblingSearchSQL, PedigreeNodeEntity.class);
2525
query.setParameter("sourceId", sourceNode);

src/main/java/org/brapi/test/BrAPITestServer/service/germ/GermplasmService.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ private void fetchPedigreeEdges(Page<GermplasmEntity> page) {
277277
searchQuery.leftJoinFetch("pedigree", "pedigree")
278278
.leftJoinFetch("*pedigree.crossingProject", "crossingProject")
279279
.leftJoinFetch("*pedigree.edges", "pedigreeEdges")
280-
.leftJoinFetch("*pedigreeEdges.conncetedNode", "connectedNode")
280+
.leftJoinFetch("*pedigreeEdges.connectedNode", "connectedNode")
281281
.appendList(page.stream()
282282
.map(BrAPIBaseEntity::getId)
283283
.collect(Collectors.toList()), "id");
@@ -326,6 +326,29 @@ public Germplasm updateGermplasm(String germplasmDbId, GermplasmNewRequest body)
326326
return convertFromEntity(savedEntity);
327327
}
328328

329+
public void deleteGermplasmBatch(List<String> germplasmDbIds) {
330+
germplasmRepository.deleteAllByIdInBatch(germplasmDbIds);
331+
}
332+
333+
public void softDeleteGermplasmBatch(List<String> germplasmDbIds) {
334+
germplasmRepository.updateSoftDeletedStatusBatch(germplasmDbIds, true);
335+
}
336+
337+
public void deleteGermplasm(String germplasmDbId) throws BrAPIServerException {
338+
// Soft delete the germplasm first since the method throws a 404 exception if the germplasm is not found
339+
softDeleteGermplasm(germplasmDbId);
340+
341+
// Hard delete the list
342+
germplasmRepository.deleteAllByIdInBatch(Arrays.asList(germplasmDbId));
343+
}
344+
345+
public void softDeleteGermplasm(String germplasmDbId) throws BrAPIServerException {
346+
int updatedCount = germplasmRepository.updateSoftDeletedStatus(germplasmDbId, true);
347+
if (updatedCount == 0) {
348+
throw new BrAPIServerDbIdNotFoundException("list", germplasmDbId, "list database ID", HttpStatus.NOT_FOUND);
349+
}
350+
}
351+
329352
public List<Germplasm> saveGermplasm(@Valid List<GermplasmNewRequest> body) throws BrAPIServerException {
330353
List<GermplasmEntity> toSave = new ArrayList<>();
331354
for (GermplasmNewRequest germplasm : body) {

src/main/java/org/brapi/test/BrAPITestServer/service/germ/PedigreeService.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.brapi.test.BrAPITestServer.model.entity.germ.CrossingProjectEntity;
1818
import org.brapi.test.BrAPITestServer.model.entity.germ.GermplasmEntity;
1919
import org.brapi.test.BrAPITestServer.model.entity.germ.PedigreeEdgeEntity;
20-
import org.brapi.test.BrAPITestServer.model.entity.germ.PedigreeEdgeEntity.EdgeType;
2120
import org.brapi.test.BrAPITestServer.model.entity.germ.PedigreeNodeEntity;
2221
import org.brapi.test.BrAPITestServer.repository.germ.PedigreeEdgeRepository;
2322
import org.brapi.test.BrAPITestServer.repository.germ.PedigreeRepository;
@@ -408,17 +407,17 @@ private PedigreeNode convertFromEntity(PedigreeNodeEntity entity, PedigreeSearch
408407
if (entity.getParentEdges() != null && request.isIncludeParents()) {
409408
node.setParents(entity.getParentEdges().stream().map(edge -> {
410409
PedigreeNodeParents parent = new PedigreeNodeParents();
411-
parent.setGermplasmDbId(edge.getConncetedNode().getGermplasm().getId());
412-
parent.setGermplasmName(edge.getConncetedNode().getGermplasm().getGermplasmName());
410+
parent.setGermplasmDbId(edge.getConnectedNode().getGermplasm().getId());
411+
parent.setGermplasmName(edge.getConnectedNode().getGermplasm().getGermplasmName());
413412
parent.setParentType(edge.getParentType());
414413
return parent;
415414
}).collect(Collectors.toList()));
416415
}
417416
if (entity.getProgenyEdges() != null && request.isIncludeProgeny()) {
418417
node.setProgeny(entity.getProgenyEdges().stream().map(edge -> {
419418
PedigreeNodeParents progeny = new PedigreeNodeParents();
420-
progeny.setGermplasmDbId(edge.getConncetedNode().getGermplasm().getId());
421-
progeny.setGermplasmName(edge.getConncetedNode().getGermplasm().getGermplasmName());
419+
progeny.setGermplasmDbId(edge.getConnectedNode().getGermplasm().getId());
420+
progeny.setGermplasmName(edge.getConnectedNode().getGermplasm().getGermplasmName());
422421
progeny.setParentType(edge.getParentType());
423422
return progeny;
424423
}).collect(Collectors.toList()));
@@ -442,10 +441,10 @@ static public String getPedigreeString(PedigreeNodeEntity entity) {
442441
if (entity.getParentEdges() != null && !entity.getParentEdges().isEmpty()) {
443442
Optional<PedigreeNodeEntity> mother = entity.getParentEdges().stream().filter(parentEdge -> {
444443
return ParentType.FEMALE == parentEdge.getParentType();
445-
}).map(PedigreeEdgeEntity::getConncetedNode).findFirst();
444+
}).map(PedigreeEdgeEntity::getConnectedNode).findFirst();
446445
Optional<PedigreeNodeEntity> father = entity.getParentEdges().stream().filter(parentEdge -> {
447446
return ParentType.MALE == parentEdge.getParentType();
448-
}).map(PedigreeEdgeEntity::getConncetedNode).findFirst();
447+
}).map(PedigreeEdgeEntity::getConnectedNode).findFirst();
449448

450449
if (mother.isPresent()) {
451450
pedStr += mother.get().getGermplasm().getGermplasmName() + "/";
@@ -493,7 +492,7 @@ private void updateEntityWithEdges(PedigreeNodeEntity entity, PedigreeNode node)
493492
if (node.getParents() != null) {
494493

495494
SearchQueryBuilder<PedigreeEdgeEntity> search = new SearchQueryBuilder<PedigreeEdgeEntity>(PedigreeEdgeEntity.class);
496-
search.appendSingle(node.getGermplasmDbId(), "conncetedNode.germplasm.id");
495+
search.appendSingle(node.getGermplasmDbId(), "connectedNode.germplasm.id");
497496
search.appendEnum(PedigreeEdgeEntity.EdgeType.child, "edgeType");
498497
Pageable defaultPageSize = PagingUtility.getPageRequest(new Metadata().pagination(new IndexPagination().pageSize(10000000)));
499498
Page<PedigreeEdgeEntity> existingParentEdges = pedigreeEdgeRepository.findAllBySearch(search, defaultPageSize);
@@ -516,7 +515,7 @@ private void updateEntityWithEdges(PedigreeNodeEntity entity, PedigreeNode node)
516515
if (node.getProgeny() != null) {
517516

518517
SearchQueryBuilder<PedigreeEdgeEntity> search = new SearchQueryBuilder<PedigreeEdgeEntity>(PedigreeEdgeEntity.class);
519-
search.appendSingle(node.getGermplasmDbId(), "conncetedNode.germplasm.id");
518+
search.appendSingle(node.getGermplasmDbId(), "connectedNode.germplasm.id");
520519
search.appendEnum(PedigreeEdgeEntity.EdgeType.parent, "edgeType");
521520
Pageable defaultPageSize = PagingUtility.getPageRequest(new Metadata().pagination(new IndexPagination().pageSize(10000000)));
522521
Page<PedigreeEdgeEntity> existingProgenyEdges = pedigreeEdgeRepository.findAllBySearch(search, defaultPageSize);

0 commit comments

Comments
 (0)