Skip to content

Commit

Permalink
Purge UPS Templates and refactor corresponding features #2783
Browse files Browse the repository at this point in the history
  • Loading branch information
vrindanayak committed Sep 24, 2020
1 parent e5ea80a commit ec96cd3
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 118 deletions.
4 changes: 2 additions & 2 deletions dcm4chee-arc-ui2/src/swagger/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@
"/aets/{aet}/rs/studies/{study}/series/{series}/instances/workitems/{upsTemplateID}": {
"$ref": "paths/workitems.json#/local.instances"
},
"/aets/{aet}/rs/studies/csv:{field}/workitems/{upsTemplateID}": {
"/aets/{aet}/rs/studies/csv:{field}/workitems/{upsTemplateUID}": {
"$ref": "paths/workitems.json#/local.studies.csv"
},
"/aets/{aet}/dimse/{movescp}/studies/workitems/{upsTemplateID}": {
Expand All @@ -1020,7 +1020,7 @@
"/aets/{aet}/dimse/{movescp}/query:{findscp}/studies/{study}/series/{series}/instances/workitems/{upsTemplateID}": {
"$ref": "paths/workitems.json#/external2.instances"
},
"/aets/{aet}/dimse/{movescp}/studies/csv:{field}/workitems/{upsTemplateID}": {
"/aets/{aet}/dimse/{movescp}/studies/csv:{field}/workitems/{upsTemplateUID}": {
"$ref": "paths/workitems.json#/external.studies.csv"
}
}
Expand Down
9 changes: 9 additions & 0 deletions dcm4chee-arc-ui2/src/swagger/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,15 @@
"type": "string"
}
},
"upsTemplateUIDPathParam": {
"name": "upsTemplateUID",
"in": "path",
"description": "UPS Template Workitem IUID",
"required": true,
"schema": {
"type": "string"
}
},
"upsTemplateIDPathParam": {
"name": "upsTemplateID",
"in": "path",
Expand Down
8 changes: 4 additions & 4 deletions dcm4chee-arc-ui2/src/swagger/paths/workitems.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@
"$ref": "../parameters.json#/archiveAETPathParam"
},
{
"$ref": "../parameters.json#/upsTemplateIDPathParam"
"$ref": "../parameters.json#/upsTemplateUIDPathParam"
},
{
"$ref": "../parameters.json#/csvFieldPathParam"
Expand Down Expand Up @@ -931,7 +931,7 @@
"description": "CSV field for Study Instance UID is specified as less than 1"
},
"404": {
"description": "No such Archive AE Title or UPS Template with specified ID not configured"
"description": "No such Archive AE Title or UPS Template Workitem with specified UID not found in DB"
},
"500": {
"description": "Internal Server Error"
Expand Down Expand Up @@ -1335,7 +1335,7 @@
"$ref": "../parameters.json#/csvPatientID"
},
{
"$ref": "../parameters.json#/upsTemplateIDPathParam"
"$ref": "../parameters.json#/upsTemplateUIDPathParam"
},
{
"$ref": "../parameters.json#/upsLabel"
Expand All @@ -1355,7 +1355,7 @@
"description": "Validation for one of the query parameters failed or CSV field for Study Instance UID specified as less than 1"
},
"404": {
"description": "No such Archive AE Title or Move SCP AE Title or UPS Template with specified ID not configured"
"description": "No such Archive AE Title or Move SCP AE Title or UPS Template Workitem with specified UID not found in DB"
},
"500": {
"description": "Internal Server Error"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.dcm4che3.data.Attributes;
import org.dcm4che3.data.IDWithIssuer;
import org.dcm4che3.net.Device;
import org.dcm4che3.util.UIDUtils;
import org.dcm4chee.arc.conf.ArchiveAEExtension;
import org.dcm4chee.arc.conf.ArchiveDeviceExtension;
import org.dcm4chee.arc.conf.UPSTemplate;
import org.dcm4chee.arc.keycloak.HttpServletRequestInfo;
import org.dcm4chee.arc.ups.UPSService;
import org.slf4j.Logger;
Expand All @@ -59,9 +59,6 @@
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -78,29 +75,27 @@ class UpsCSV {
private final HttpServletRequestInfo httpServletRequestInfo;
private final ArchiveAEExtension arcAE;
private final int studyUIDField;
private final UPSTemplate upsTemplate;
private final Attributes upsTemplateAttrs;
private final char csvDelimiter;

public UpsCSV(Device device, UPSService upsService, HttpServletRequestInfo httpServletRequestInfo,
ArchiveAEExtension arcAE, int studyUIDField, UPSTemplate upsTemplate, char csvDelimiter) {
ArchiveAEExtension arcAE, int studyUIDField, Attributes upsTemplateAttrs, char csvDelimiter) {
this.device = device;
this.upsService = upsService;
this.httpServletRequestInfo = httpServletRequestInfo;
this.arcAE = arcAE;
this.studyUIDField = studyUIDField;
this.upsTemplate = upsTemplate;
this.upsTemplateAttrs = upsTemplateAttrs;
this.csvDelimiter = csvDelimiter;
}

Response createWorkitems(String upsLabel, String scheduledTime, int patientIDField, String movescp, InputStream in) {
Response createWorkitems(int patientIDField, String movescp, InputStream in) {
Response.Status status = Response.Status.NO_CONTENT;
int count = 0;
String warning = null;
ArchiveDeviceExtension arcDev = device.getDeviceExtensionNotNull(ArchiveDeviceExtension.class);
int csvUploadChunkSize = arcDev.getCSVUploadChunkSize();
Map<String, IDWithIssuer> studyPatientMap = new HashMap<>();
Calendar now = Calendar.getInstance();
Date upsScheduledTime = toDate(scheduledTime);
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
CSVParser parser = new CSVParser(reader, CSVFormat.DEFAULT.withDelimiter(csvDelimiter))
Expand All @@ -125,27 +120,22 @@ Response createWorkitems(String upsLabel, String scheduledTime, int patientIDFie

if (studyPatientMap.size() == csvUploadChunkSize) {
count += upsService.createUPSRecords(
httpServletRequestInfo,
arcAE,
upsTemplate,
studyPatientMap,
upsScheduledTime,
now,
upsLabel,
movescp);
httpServletRequestInfo,
arcAE,
upsTemplateAttrs,
studyPatientMap,
movescp);
studyPatientMap.clear();
}
}

if (!studyPatientMap.isEmpty())
count += upsService.createUPSRecords(
httpServletRequestInfo,
arcAE,
upsTemplate,
studyPatientMap,
upsScheduledTime,
now,
upsLabel,
movescp);
httpServletRequestInfo,
arcAE,
upsTemplateAttrs,
studyPatientMap,
movescp);

if (count == 0)
warning = "Empty file or Incorrect field position or Not a CSV file or Invalid UIDs.";
Expand All @@ -158,7 +148,7 @@ Response createWorkitems(String upsLabel, String scheduledTime, int patientIDFie

LOG.warn("Response {} caused by {}", status, warning);
Response.ResponseBuilder builder = Response.status(status)
.header("Warning", warning);
.header("Warning", warning);
if (count > 0)
builder.entity(count(count));

Expand All @@ -172,16 +162,6 @@ private boolean validateUID(String uid) {
return valid;
}

private Date toDate(String upsScheduledTime) {
if (upsScheduledTime != null)
try {
return new SimpleDateFormat("yyyyMMddhhmmss").parse(upsScheduledTime);
} catch (Exception e) {
LOG.info(e.getMessage());
}
return null;
}

private static String count(int count) {
return "{\"count\":" + count + '}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.dcm4chee.arc.ups.UPSContext;
import org.dcm4chee.arc.ups.UPSService;
import org.dcm4chee.arc.ups.UPSUtils;
import org.dcm4chee.arc.ups.impl.UPSContextImpl;
import org.dcm4chee.arc.validation.constraints.InvokeValidate;
import org.dcm4chee.arc.validation.constraints.ValidValueOf;
import org.slf4j.Logger;
Expand All @@ -82,6 +83,7 @@
import java.util.Date;
import java.util.EnumSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntFunction;

/**
* @author Vrinda Nayak <vrinda.nayak@j4care.com>
Expand Down Expand Up @@ -195,13 +197,13 @@ public Response upsQueryFindSCPMatchingInstances(
}

@POST
@Path("/studies/csv:{field}/workitems/{upsTemplateID}")
@Path("/studies/csv:{field}/workitems/{upsTemplateUID}")
public Response createWorkitems(
@PathParam("field") int field,
@PathParam("upsTemplateID") String upsTemplateID,
@PathParam("upsTemplateUID") String upsTemplateUID,
@QueryParam("csvPatientID") String csvPatientIDField,
InputStream in) {
return createWorkitemsFromCSV(field, upsTemplateID, upsLabel, upsScheduledTime, csvPatientIDField, in);
return createWorkitemsFromCSV(field, upsTemplateUID, csvPatientIDField, in);
}

private Response upsMatching(QueryRetrieveLevel2 level, String upsTemplateID,
Expand Down Expand Up @@ -314,8 +316,8 @@ private void createUPS(ArchiveAEExtension arcAE, Attributes ups, AtomicInteger c
}
}

private Response createWorkitemsFromCSV(int studyUIDField, String upsTemplateID, String upsLabel, String scheduledTime,
String csvPatientIDField, InputStream in) {
private Response createWorkitemsFromCSV(
int studyUIDField, String upsTemplateUID, String csvPatientIDField, InputStream in) {
if (studyUIDField < 1)
return errResponse(Response.Status.BAD_REQUEST,
"CSV field for Study Instance UID should be greater than or equal to 1");
Expand All @@ -327,23 +329,20 @@ private Response createWorkitemsFromCSV(int studyUIDField, String upsTemplateID,

try {
aeCache.findApplicationEntity(moveSCP);
ArchiveDeviceExtension arcDev = device.getDeviceExtensionNotNull(ArchiveDeviceExtension.class);
UPSTemplate upsTemplate = arcDev.getUPSTemplate(upsTemplateID);
if (upsTemplate == null)
return errResponse(Response.Status.NOT_FOUND, "No such UPS Template: " + upsTemplateID);

ApplicationEntity ae = device.getApplicationEntity(aet, true);
if (ae == null || !ae.isInstalled())
ArchiveAEExtension arcAE = getArchiveAE();
if (arcAE == null)
return errResponse(Response.Status.NOT_FOUND, "No such Application Entity: " + aet);

UpsCSV upsCSV = new UpsCSV(device,
upsService,
HttpServletRequestInfo.valueOf(request),
ae.getAEExtensionNotNull(ArchiveAEExtension.class),
arcAE,
studyUIDField,
upsTemplate,
upsTemplateAttrs(upsTemplateUID, arcAE),
csvDelimiter());
return upsCSV.createWorkitems(upsLabel, scheduledTime, patientIDField, moveSCP, in);
return upsCSV.createWorkitems(patientIDField, moveSCP, in);
} catch (DicomServiceException e) {
return errResponse(UpsDimseRS::createFailed, e);
} catch (IllegalStateException | ConfigurationException e) {
return errResponse(Response.Status.NOT_FOUND, e.getMessage());
} catch (Exception e) {
Expand Down Expand Up @@ -373,6 +372,22 @@ public void validate() {
new QueryAttributes(uriInfo, null);
}

private Attributes upsTemplateAttrs(String upsTemplateUID, ArchiveAEExtension arcAE) throws DicomServiceException {
UPSContext ctx = upsService.newUPSContext(HttpServletRequestInfo.valueOf(request), arcAE);
ctx.setUPSInstanceUID(upsTemplateUID);
Attributes upsAttrs = upsService.findUPS(ctx).getAttributes();
upsAttrs.setDate(Tag.ScheduledProcedureStepStartDateTime, VR.DT, scheduledTime());
if (upsLabel != null)
upsAttrs.setString(Tag.ProcedureStepLabel, VR.LO, upsLabel);
return upsAttrs;
}

private ArchiveAEExtension getArchiveAE() {
ApplicationEntity ae = device.getApplicationEntity(aet, true);
return ae != null && ae.isInstalled()
? ae.getAEExtensionNotNull(ArchiveAEExtension.class) : null;
}

private Duration splitStudyDateRange() {
return splitStudyDateRange != null ? Duration.valueOf(splitStudyDateRange) : null;
}
Expand All @@ -384,7 +399,7 @@ private Date scheduledTime() {
} catch (Exception e) {
LOG.info(e.getMessage());
}
return null;
return new Date();
}

private static int parseInt(String s, int defval) {
Expand Down Expand Up @@ -430,6 +445,26 @@ public String toString() {
return queryString == null ? requestURI : requestURI + '?' + queryString;
}

private static Response.Status createFailed(int status) {
switch (status) {
case Status.UPSDoesNotExist:
return Response.Status.NOT_FOUND;
case Status.DuplicateSOPinstance:
return Response.Status.CONFLICT;
case Status.UPSNotScheduled:
case Status.NoSuchAttribute:
case Status.MissingAttribute:
case Status.MissingAttributeValue:
case Status.InvalidAttributeValue:
return Response.Status.BAD_REQUEST;
}
return Response.Status.INTERNAL_SERVER_ERROR;
}

private Response errResponse(IntFunction<Response.Status> httpStatusOf, DicomServiceException e) {
return errResponse(httpStatusOf.apply(e.getStatus()), e.getMessage());
}

private Response errResponse(Response.Status status, String msg) {
return errResponseAsTextPlain("{\"errorMessage\":\"" + msg + "\"}", status);
}
Expand Down
Loading

0 comments on commit ec96cd3

Please sign in to comment.