Skip to content

Commit

Permalink
#374 - Extend API to save and load cohort and dataselection
Browse files Browse the repository at this point in the history
- add check if user has stored too many dataqueries with result
- fix missing result size in get dataquery
- start working on more tests (lot of code commented out)
  • Loading branch information
michael-82 committed Feb 26, 2025
1 parent be1b8c6 commit 6f569c5
Show file tree
Hide file tree
Showing 10 changed files with 1,818 additions and 1,454 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ public StructuredQuery getQueryContent(Long queryId) throws JsonProcessingExcept
}
}

public Long storeDataquery(Dataquery dataquery, String userId)
throws DataqueryException {
return dataqueryHandler.storeDataquery(dataquery, userId);
}

private Query convertQueryToApi(de.numcodex.feasibility_gui_backend.query.persistence.Query in)
throws JsonProcessingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ public class DataqueryHandler {
@Value("${app.maxSavedQueriesPerUser}")
private int maxDataqueriesPerUser;

public Long storeDataquery(@NonNull Dataquery dataquery, @NonNull String userId) throws DataqueryException {
public Long storeDataquery(@NonNull Dataquery dataquery, @NonNull String userId) throws DataqueryException, DataqueryStorageFullException {
var usedSlots = dataqueryRepository.countByCreatedByWhereResultIsNotNull(userId);

if (usedSlots >= maxDataqueriesPerUser) {
throw new DataqueryStorageFullException();
}

var tmp = Dataquery.builder()
.resultSize(dataquery.resultSize())
.content(dataquery.content())
Expand All @@ -57,8 +63,18 @@ public Dataquery getDataqueryById(Long dataqueryId, String userId) throws Dataqu
return convertPersistenceToApi(dataquery);
}

public void updateDataquery(Long queryId, Dataquery dataquery, String userId) throws DataqueryException, JsonProcessingException {
public void updateDataquery(Long queryId, Dataquery dataquery, String userId) throws DataqueryException, DataqueryStorageFullException, JsonProcessingException {
var usedSlots = dataqueryRepository.countByCreatedByWhereResultIsNotNull(userId);
var existingDataquery = dataqueryRepository.findById(queryId).orElseThrow(DataqueryException::new);

if (usedSlots >= maxDataqueriesPerUser) {
// Only throw an exception when the updated query contains a result and the original didn't
if (dataquery.resultSize() != null && existingDataquery.getResultSize() == null) {
throw new DataqueryStorageFullException();
}
}


if (existingDataquery.getCreatedBy().equals(userId)) {
var dataqueryToUpdate = convertApiToPersistence(dataquery);
dataqueryToUpdate.setId(existingDataquery.getId());
Expand Down Expand Up @@ -94,7 +110,7 @@ public void deleteDataquery(Long dataqueryId, String userId) throws DataqueryExc
}

public SavedQuerySlots getDataquerySlotsJson(String userId) {
var queryAmount = dataqueryRepository.countByCreatedBy(userId);
var queryAmount = dataqueryRepository.countByCreatedByWhereResultIsNotNull(userId);

return SavedQuerySlots.builder()
.used(queryAmount)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.numcodex.feasibility_gui_backend.query.dataquery;

public class DataqueryStorageFullException extends Exception {

public DataqueryStorageFullException() {
super();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@

public interface DataqueryRepository extends JpaRepository<Dataquery, Long> {
List<Dataquery> findAllByCreatedBy(String userId);
Long countByCreatedBy(String userId);

@Query(value = "SELECT COUNT(*) FROM Dataquery WHERE createdBy = ?1 AND resultSize IS NOT NULL")
Long countByCreatedByWhereResultIsNotNull(String userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import de.numcodex.feasibility_gui_backend.query.api.Crtdl;
import de.numcodex.feasibility_gui_backend.query.api.Dataquery;
import de.numcodex.feasibility_gui_backend.query.api.status.SavedQuerySlots;
import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryException;
import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryHandler;
import de.numcodex.feasibility_gui_backend.query.dataquery.DataqueryStorageFullException;
import de.numcodex.feasibility_gui_backend.terminology.validation.StructuredQueryValidation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.core.Context;
Expand Down Expand Up @@ -55,8 +57,12 @@ public ResponseEntity<Object> storeDataquery(@RequestBody Dataquery dataquery,
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (DataIntegrityViolationException e) {
return new ResponseEntity<>(HttpStatus.CONFLICT);
} catch (DataqueryStorageFullException e) {
return new ResponseEntity<>("storage exceeded", HttpStatus.FORBIDDEN);
}

var dataquerySlots = dataqueryHandler.getDataquerySlotsJson(principal.getName());

UriComponentsBuilder uriBuilder = (apiBaseUrl != null && !apiBaseUrl.isEmpty())
? ServletUriComponentsBuilder.fromUriString(apiBaseUrl)
: ServletUriComponentsBuilder.fromRequestUri(httpServletRequest);
Expand All @@ -67,7 +73,7 @@ public ResponseEntity<Object> storeDataquery(@RequestBody Dataquery dataquery,
.toUriString();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.LOCATION, uriString);
return new ResponseEntity<>(httpHeaders, HttpStatus.CREATED);
return new ResponseEntity<>(dataquerySlots, httpHeaders, HttpStatus.CREATED);
}

@GetMapping(path = "/{dataqueryId}")
Expand All @@ -77,7 +83,7 @@ public ResponseEntity<Object> getDataquery(@PathVariable(value = "dataqueryId")

try {
var dataquery = dataqueryHandler.getDataqueryById(dataqueryId, principal.getName());
var dataqueryWithInvalidCritiera = Dataquery.builder()
var dataqueryWithInvalidCriteria = Dataquery.builder()
.id(dataquery.id())
.content(
Crtdl.builder()
Expand All @@ -92,8 +98,9 @@ public ResponseEntity<Object> getDataquery(@PathVariable(value = "dataqueryId")
.lastModified(dataquery.lastModified())
.createdBy(dataquery.createdBy())
.isValid(dataquery.isValid())
.resultSize(dataquery.resultSize())
.build();
return new ResponseEntity<>(dataqueryWithInvalidCritiera, HttpStatus.OK);
return new ResponseEntity<>(dataqueryWithInvalidCriteria, HttpStatus.OK);
} catch (JsonProcessingException e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (DataqueryException e) {
Expand Down Expand Up @@ -139,6 +146,7 @@ public ResponseEntity<Object> getDataqueries(
.comment(dq.comment())
.lastModified(dq.lastModified())
.createdBy(dq.createdBy())
.resultSize(dq.resultSize())
.build()
);
} else {
Expand All @@ -149,6 +157,7 @@ public ResponseEntity<Object> getDataqueries(
.comment(dq.comment())
.lastModified(dq.lastModified())
.createdBy(dq.createdBy())
.resultSize(dq.resultSize())
.isValid(structuredQueryValidation.isValid(dq.content().cohortDefinition()))
.build()
);
Expand Down Expand Up @@ -203,11 +212,14 @@ public ResponseEntity<Object> updateDataquery(@PathVariable(value = "dataqueryId
Principal principal) {
try {
dataqueryHandler.updateDataquery(dataqueryId, dataquery, principal.getName());
return new ResponseEntity<>(HttpStatus.OK);
var dataquerySlots = dataqueryHandler.getDataquerySlotsJson(principal.getName());
return new ResponseEntity<>(dataquerySlots, HttpStatus.OK);
} catch (DataqueryException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} catch (JsonProcessingException e) {
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
} catch (DataqueryStorageFullException e) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}

Expand Down
Loading

0 comments on commit 6f569c5

Please sign in to comment.