Skip to content

Commit

Permalink
Merge branch 'develop' into issue#2592_shup_mass_import_bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentPV authored Feb 26, 2025
2 parents c3e720f + 436c808 commit 2e4ebb3
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,11 @@ public ResponseEntity<Void> deleteDataset(
if (ds == null) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
LOG.info("Deletion of dataset with ID: " + ds.getId());
Long studyId = datasetService.getStudyId(ds);


datasetService.deleteById(datasetId);
solrService.deleteFromIndex(datasetId);
rabbitTemplate.convertAndSend(RabbitMQConfiguration.RELOAD_BIDS, objectMapper.writeValueAsString(studyId));

return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (EntityNotFoundException | RestServiceException e) {
throw e;
Expand All @@ -187,6 +185,10 @@ public ResponseEntity<Void> deleteDatasets(
@RequestBody List<Long> datasetIds)
throws RestServiceException {
try {
if (datasetIds.size() > DATASET_LIMIT) {
throw new RestServiceException(
new ErrorModel(HttpStatus.FORBIDDEN.value(), "This selection includes " + datasetIds.size() + " datasets. You can't delete more than " + DATASET_LIMIT + " datasets."));
}
datasetService.deleteByIdIn(datasetIds);
solrService.deleteFromIndex(datasetIds);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public interface DatasetService {
List<Dataset> findByStudycard(Long studycardId);

@PreAuthorize("hasRole('ADMIN') or (hasRole('EXPERT') and @datasetSecurityService.hasRightOnDataset(#dataset.getId(), 'CAN_ADMINISTRATE'))")
void deleteDatasetFromPacs(Dataset dataset) throws ShanoirException;
void deleteDatasetFromDiskAndPacs(Dataset dataset) throws ShanoirException;

boolean existsById(Long id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ private void delete(Dataset entity) throws ShanoirException, SolrServerException
public void deleteById(final Long id) throws ShanoirException, SolrServerException, IOException, RestServiceException {
final Dataset dataset = repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(Dataset.class, id));

// Do not delete entity if it is the source (or if it has copies). If getSourceId() is not null, it means it's a copy
if (!CollectionUtils.isEmpty(dataset.getCopies())) {
throw new RestServiceException(
Expand All @@ -151,10 +150,12 @@ public void deleteById(final Long id) throws ShanoirException, SolrServerExcepti
"This dataset is linked to another dataset that was copied."
));
}

long startTime = System.currentTimeMillis();
delete(dataset);

this.deleteDatasetFromPacs(dataset);
deleteDatasetFromDiskAndPacs(dataset);
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
LOG.info("Dataset deletion time: " + elapsedTime + " milliseconds");
}

/**
Expand Down Expand Up @@ -182,28 +183,27 @@ public void deleteByIdCascade(final Long id) throws ShanoirException, SolrServer
}

@Override
public void deleteDatasetFromPacs(Dataset dataset) throws ShanoirException {
public void deleteDatasetFromDiskAndPacs(Dataset dataset) throws ShanoirException {
if (!dicomWeb) {
return;
}

for (DatasetExpression expression : dataset.getDatasetExpressions()) {
boolean isDicom = DatasetExpressionFormat.DICOM.equals(expression.getDatasetExpressionFormat());

for (DatasetFile file : expression.getDatasetFiles()) {
// DICOM
if (isDicom && file.isPacs()) {
dicomWebService.rejectDatasetFromPacs(file.getPath());
// NIfTI
} else if (!file.isPacs()) {
try {
URL url = new URL(file.getPath().replaceAll("%20", " "));
File srcFile = new File(UriUtils.decode(url.getPath(), "UTF-8"));
FileUtils.deleteQuietly(srcFile);
} catch (MalformedURLException e) {
throw new ShanoirException("Error while deleting dataset file", e);
throw new ShanoirException("Error while deleting dataset file.", e);
}
}
}
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,16 @@ public ResponseEntity<String> findSeriesOfStudy(String examinationUID, Map<Strin
acquisitionUID = allParams.get(SERIES_INSTANCE_UID);
seriesInstanceUID = seriesInstanceUIDHandler.findSeriesInstanceUIDFromCacheOrDatabase(acquisitionUID);
}

if (studyInstanceUID != null) {
String response = dicomWebService.findSeriesOfStudy(studyInstanceUID, includefield, seriesInstanceUID);
JsonNode root = mapper.readTree(response);
root = sortSeriesBySeriesNumber(root);
studyInstanceUIDHandler.replaceStudyInstanceUIDsWithExaminationUIDs(root, examinationUID, false);

return new ResponseEntity<String>(mapper.writeValueAsString(root), HttpStatus.OK);
if (response != null) {
JsonNode root = mapper.readTree(response);
root = sortSeriesBySeriesNumber(root);
studyInstanceUIDHandler.replaceStudyInstanceUIDsWithExaminationUIDs(root, examinationUID, false);
return new ResponseEntity<String>(mapper.writeValueAsString(root), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
else {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ public ResponseEntity findInstance(String studyInstanceUID, String serieInstance
if (entity != null) {
ByteArrayResource byteArrayResource = new ByteArrayResource(EntityUtils.toByteArray(entity));
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentLength(entity.getContentLength());
if (!entity.isChunked() && entity.getContentLength() >= 0) {
responseHeaders.setContentLength(entity.getContentLength());
}
return new ResponseEntity(byteArrayResource, responseHeaders, HttpStatus.OK);
} else {
LOG.error("DICOMWeb: findInstance: empty response entity.");
Expand Down Expand Up @@ -298,13 +300,11 @@ private void sendMultipartRequest(HttpEntity entity) throws ShanoirException {

public void rejectExaminationFromPacs(String studyInstanceUID) throws ShanoirException {
String rejectURL = this.serverURL + "/" + studyInstanceUID + REJECT_SUFFIX;

rejectURLFromPacs(rejectURL);
}

public void rejectAcquisitionFromPacs(String studyInstanceUID, String seriesInstanceUID) throws ShanoirException {
String rejectURL = this.serverURL + "/" + studyInstanceUID + "/series/" + seriesInstanceUID + REJECT_SUFFIX;

rejectURLFromPacs(rejectURL);
}

Expand All @@ -324,12 +324,12 @@ private void rejectURLFromPacs(String url) throws ShanoirException {
post.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON);
try (CloseableHttpResponse response = httpClient.execute(post)) {
if (HttpStatus.OK.value() == response.getCode()) {
LOG.info("Rejected from PACS: " + post);
LOG.debug("Rejected from PACS: " + post);
} else {
LOG.error(response.getCode() + ": Could not reject instance from PACS: " + response.getReasonPhrase()
+ " for rejectURL: " + url);
// in case one URL is Not Found (no DICOM instance present), we continue with deletion
if (response.getCode() == 404 && response.getReasonPhrase().startsWith("Not Found")) {
LOG.error("Could not delete from pacs: " + response.getCode() + " " + response.getReasonPhrase());
return;
} else {
throw new ShanoirException(response.getCode() + ": Could not reject instance from PACS: " + response.getReasonPhrase()
Expand All @@ -345,13 +345,13 @@ private void rejectURLFromPacs(String url) throws ShanoirException {
@Scheduled(cron = "0 */30 * * * *", zone="Europe/Paris")
public void deleteDicomFilesFromPacs() throws ShanoirException {
// Doc : https://smart-api.info/ui/be87344696148a41f577aca202ce84df#/IOCM-RS/deleteRejectedInstancesPermanently
LOG.error("Scheduled call to delete all rejected instances from pacs.");
LOG.info("Scheduled call to delete all rejected instances from pacs.");
String url = this.serverURL.substring(0, this.serverURL.indexOf("/aets/")) + REJECT_SUFFIX;
HttpDelete httpDelete = new HttpDelete(url);
httpDelete.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON);
try (CloseableHttpResponse response = httpClient.execute(httpDelete)) {
if (response.getCode() == HttpStatus.OK.value()) {
LOG.error("Deleted from PACS: " + url);
LOG.info("Deleted from PACS: " + url);
} else {
LOG.error(response.getCode() + ": Could not delete instance from PACS: " + response.getReasonPhrase()
+ "for deleteURL: " + url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private Examination modifyDicom(Attributes datasetAttributes) {
Examination examination = examinationRepository.findById(examinationID).get();
// replace artificial examinationUID with real StudyInstanceUID in DICOM server
String studyInstanceUID = studyInstanceUIDHandler.findStudyInstanceUIDFromCacheOrDatabase(examinationUID);
datasetAttributes.setString(Tag.StudyInstanceUID, VR.UI, studyInstanceUID);
datasetAttributes.setString(Tag.StudyInstanceUID, VR.UI, studyInstanceUID);
// replace subject name, that is sent by the viewer wrongly with P-0000001 etc.
Optional<Subject> subjectOpt = subjectRepository.findById(examination.getSubject().getId());
String subjectName = "error_subject_name_not_found_in_db";
Expand All @@ -163,7 +163,7 @@ private Examination modifyDicom(Attributes datasetAttributes) {
}
datasetAttributes.setString(Tag.PatientName, VR.PN, subjectName);
datasetAttributes.setString(Tag.PatientID, VR.LO, subjectName);
// set user name, as person, who created the measurement
// set user name, as person, who created the measurement/segmentation
final String userName = KeycloakUtil.getTokenUserName();
datasetAttributes.setString(Tag.PersonName, VR.PN, userName);
// set as well person observer name in content sequence
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,20 +234,20 @@ private void testDelete(String role) throws ShanoirException {
if ("ROLE_USER".equals(role)) {
given(rightsService.hasRightOnStudy(1L, "CAN_ADMINISTRATE")).willReturn(true);
given(rightsService.hasRightOnStudies(Utils.toSet(1L), "CAN_ADMINISTRATE")).willReturn(Utils.toSet(1L));
assertAccessDenied(service::deleteDatasetFromPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessDenied(service::deleteDatasetFromDiskAndPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessDenied(service::deleteById, 1L);
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 2L, 3L, 4L));
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 3L));
} else if ("ROLE_EXPERT".equals(role)) {
given(rightsService.hasRightOnStudy(1L, "CAN_ADMINISTRATE")).willReturn(false);
given(rightsService.hasRightOnStudies(Utils.toSet(1L), "CAN_ADMINISTRATE")).willReturn(Utils.toSet());
assertAccessDenied(service::deleteDatasetFromPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessDenied(service::deleteDatasetFromDiskAndPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessDenied(service::deleteById, 1L);
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 2L, 3L, 4L));
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 3L));
given(rightsService.hasRightOnStudy(1L, "CAN_ADMINISTRATE")).willReturn(true);
given(rightsService.hasRightOnStudies(Utils.toSet(1L), "CAN_ADMINISTRATE")).willReturn(Utils.toSet(1L));
assertAccessAuthorized(service::deleteDatasetFromPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessAuthorized(service::deleteDatasetFromDiskAndPacs, mockDataset(1L, 1L, 1L, 1L, 1L));
assertAccessAuthorized(service::deleteById, 1L);
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 2L, 3L, 4L));
assertAccessDenied(service::deleteByIdIn, Utils.toList(1L, 3L));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
</span>
</td>
<td>
<button type="button" *ngIf="!pagings.get(qualityCard.id)" class="alt right-icon apply" (click)="apply(qualityCard)" [disabled]="loading.get(qualityCard.id)">
<button type="button" *ngIf="!pagings.get(qualityCard.id)" class="alt right-icon apply" (click)="apply(qualityCard)" [disabled]="true || loading.get(qualityCard.id)">
Apply now
<i *ngIf="!loading.get(qualityCard.id)" class="fa-solid fa-play"></i>
<i *ngIf="loading.get(qualityCard.id)" class="fa fa-cog fa-spin"></i>
Expand Down

0 comments on commit 2e4ebb3

Please sign in to comment.