use of org.dcm4chee.arc.conf.ArchiveAEExtension in project dcm4chee-arc-light by dcm4che.
the class CommonCGetSCP method calculateMatches.
@Override
protected RetrieveTask calculateMatches(Association as, PresentationContext pc, Attributes rq, Attributes keys) throws DicomServiceException {
LOG.info("{}: Process C-GET RQ:\n{}", as, keys);
EnumSet<QueryOption> queryOpts = as.getQueryOptionsFor(rq.getString(Tag.AffectedSOPClassUID));
QueryRetrieveLevel2 qrLevel = QueryRetrieveLevel2.validateRetrieveIdentifier(keys, qrLevels, queryOpts.contains(QueryOption.RELATIONAL), relationalRetrieveNegotiationLenient(as));
ArchiveAEExtension arcAE = as.getApplicationEntity().getAEExtension(ArchiveAEExtension.class);
RetrieveContext ctx = retrieveService.newRetrieveContextGET(arcAE, as, rq, qrLevel, keys);
if (!retrieveService.calculateMatches(ctx))
return null;
return storeSCU.newRetrieveTaskGET(as, pc, rq, ctx);
}
use of org.dcm4chee.arc.conf.ArchiveAEExtension in project dcm4chee-arc-light by dcm4che.
the class CommonCMoveSCP method calculateMatches.
@Override
protected RetrieveTask calculateMatches(Association as, PresentationContext pc, Attributes rq, Attributes keys) throws DicomServiceException {
LOG.info("{}: Process C-MOVE RQ:\n{}", as, keys);
EnumSet<QueryOption> queryOpts = as.getQueryOptionsFor(rq.getString(Tag.AffectedSOPClassUID));
QueryRetrieveLevel2 qrLevel = QueryRetrieveLevel2.validateRetrieveIdentifier(keys, qrLevels, queryOpts.contains(QueryOption.RELATIONAL), relationalRetrieveNegotiationLenient(as));
ArchiveAEExtension arcAE = as.getApplicationEntity().getAEExtension(ArchiveAEExtension.class);
if (!arcAE.isAcceptedMoveDestination(rq.getString(Tag.MoveDestination)))
throw new DicomServiceException(RetrieveService.MOVE_DESTINATION_NOT_ALLOWED, RetrieveService.MOVE_DESTINATION_NOT_ALLOWED_MSG);
RetrieveContext ctx = newRetrieveContext(arcAE, as, rq, qrLevel, keys);
String fallbackCMoveSCP = arcAE.fallbackCMoveSCP();
String fallbackCMoveSCPCallingAET = arcAE.fallbackCMoveSCPCallingAET(as);
String fallbackCMoveSCPDestination = arcAE.fallbackCMoveSCPDestination();
if (!retrieveService.calculateMatches(ctx)) {
if (fallbackCMoveSCP == null)
return null;
ctx.setRetryFailedRetrieve(true);
LOG.info("{}: No objects of study{} found - forward C-MOVE RQ to {}", as, Arrays.toString(ctx.getStudyInstanceUIDs()), fallbackCMoveSCP);
return moveSCU.newForwardRetrieveTask(ctx, pc, rq, keys, fallbackCMoveSCPCallingAET, fallbackCMoveSCP, fallbackCMoveSCPDestination);
}
if (!retrieveService.restrictRetrieveAccordingTransferCapabilities(ctx)) {
if (ctx.failed() > 0) {
throw new DicomServiceException(Status.UnableToPerformSubOperations).setNumberOfCompletedFailedWarningSuboperations(ctx.completed(), ctx.failed(), ctx.warning());
}
return null;
}
Map<String, Collection<InstanceLocations>> notAccessable = retrieveService.removeNotAccessableMatches(ctx);
String altCMoveSCP = arcAE.alternativeCMoveSCP();
if (ctx.getMoveOriginatorAETitle().equals(altCMoveSCP)) {
// mask altCMoveSCP in Move Originator AET in C-STORE RQ - assume Destination originated Move RQ to altCMoveSCP
ctx.setMoveOriginatorAETitle(ctx.getDestinationAETitle());
// ignore not accessible matches - assume they are handled by altCMoveSCP
ctx.setNumberOfMatches(ctx.getMatches().size());
} else {
boolean retryFailedRetrieve = fallbackCMoveSCP != null && fallbackCMoveSCPDestination != null && retryFailedRetrieve(ctx, qrLevel);
// TODO
Collection<InstanceLocations> notRetrieveable = notAccessable.remove(null);
Iterator<Map.Entry<String, Collection<InstanceLocations>>> notAccessableIter = notAccessable.entrySet().iterator();
if (notAccessableIter.hasNext()) {
Map.Entry<String, Collection<InstanceLocations>> notAccessableNext = notAccessableIter.next();
String otherCMoveSCP = notAccessableNext.getKey();
String otherMoveDest = otherCMoveSCP.equals(altCMoveSCP) ? null : arcAE.externalRetrieveAEDestination();
while (notAccessableIter.hasNext()) {
LOG.info("{}: {} objects of study{} not locally accessable - send C-MOVE RQ to {}", as, notAccessableNext.getValue().size(), Arrays.toString(ctx.getStudyInstanceUIDs()), otherCMoveSCP);
moveSCU.forwardMoveRQ(ctx, pc, rq, keys, null, otherCMoveSCP, otherMoveDest);
notAccessableNext = notAccessableIter.next();
otherCMoveSCP = notAccessableNext.getKey();
otherMoveDest = otherCMoveSCP.equals(altCMoveSCP) ? null : arcAE.externalRetrieveAEDestination();
}
LOG.info("{}: {} objects of study{} not locally accessable - send C-MOVE RQ to {}", as, notAccessableNext.getValue().size(), Arrays.toString(ctx.getStudyInstanceUIDs()), otherCMoveSCP);
if (!retryFailedRetrieve && ctx.getMatches().isEmpty()) {
return moveSCU.newForwardRetrieveTask(ctx, pc, rq, keys, null, otherCMoveSCP, otherMoveDest);
}
moveSCU.forwardMoveRQ(ctx, pc, rq, keys, null, otherCMoveSCP, otherMoveDest);
}
if (retryFailedRetrieve) {
ctx.setRetryFailedRetrieve(true);
LOG.info("{}: Some objects of study{} not found - retry forward C-MOVE RQ to {}", as, Arrays.toString(ctx.getStudyInstanceUIDs()), fallbackCMoveSCP);
if (ctx.getMatches().isEmpty())
return moveSCU.newForwardRetrieveTask(ctx, pc, rq, keys, fallbackCMoveSCPCallingAET, fallbackCMoveSCP, fallbackCMoveSCPDestination);
moveSCU.forwardMoveRQ(ctx, pc, rq, keys, fallbackCMoveSCPCallingAET, fallbackCMoveSCP, fallbackCMoveSCPDestination);
}
}
return storeSCU.newRetrieveTaskMOVE(as, pc, rq, ctx);
}
use of org.dcm4chee.arc.conf.ArchiveAEExtension in project dcm4chee-arc-light by dcm4che.
the class CommonCMoveSCP method retryFailedRetrieve.
private boolean retryFailedRetrieve(RetrieveContext ctx, QueryRetrieveLevel2 qrLevel) {
HashSet<String> uids = new HashSet<>();
ArchiveAEExtension arcae = ctx.getArchiveAEExtension();
int maxRetrieveRetries = arcae.fallbackCMoveSCPRetries();
switch(qrLevel) {
case STUDY:
uids.addAll(Arrays.asList(ctx.getStudyInstanceUIDs()));
for (StudyInfo studyInfo : ctx.getStudyInfos()) {
if (studyInfo.getCompleteness() != Completeness.COMPLETE) {
if (maxRetrieveRetries == 0 || studyInfo.getFailedRetrieves() < maxRetrieveRetries)
return true;
LOG.warn("{}: Maximal number of retries[{}] to retrieve objects of study[{}] from {} exceeded", ctx.getRequestAssociation(), maxRetrieveRetries, studyInfo.getStudyInstanceUID(), arcae.fallbackCMoveSCP());
}
uids.remove(studyInfo.getStudyInstanceUID());
}
case SERIES:
uids.addAll(Arrays.asList(ctx.getSeriesInstanceUIDs()));
for (SeriesInfo seriesInfo : ctx.getSeriesInfos()) {
if (seriesInfo.getCompleteness() != Completeness.COMPLETE) {
if (maxRetrieveRetries == 0 || seriesInfo.getFailedRetrieves() < maxRetrieveRetries)
return true;
LOG.warn("{}: Maximal number of retries[{}] to retrieve objects of series[{}] from {} exceeded", ctx.getRequestAssociation(), maxRetrieveRetries, seriesInfo.getSeriesInstanceUID(), arcae.fallbackCMoveSCP());
}
uids.remove(seriesInfo.getSeriesInstanceUID());
}
}
return !uids.isEmpty();
}
use of org.dcm4chee.arc.conf.ArchiveAEExtension in project dcm4chee-arc-light by dcm4che.
the class PamRS method createPatient.
@POST
@Path("/patients")
@Consumes({ "application/dicom+json,application/json" })
@Produces("application/json")
public String createPatient(InputStream in) {
ArchiveAEExtension arcAE = getArchiveAE();
try {
PatientMgtContext ctx = patientMgtCtx(in);
ctx.setArchiveAEExtension(arcAE);
if (!ctx.getAttributes().containsValue(Tag.PatientID)) {
idService.newPatientID(ctx.getAttributes());
ctx.setPatientID(IDWithIssuer.pidOf(ctx.getAttributes()));
}
patientService.updatePatient(ctx);
rsForward.forward(RSOperation.CreatePatient, arcAE, ctx.getAttributes(), request);
notifyHL7Receivers("ADT^A28^ADT_A05", ctx);
return "{\"PatientID\":\"" + IDWithIssuer.pidOf(ctx.getAttributes()) + "\"}";
} catch (NonUniquePatientException e) {
throw new WebApplicationException(errResponse(e.getMessage(), Response.Status.CONFLICT));
} catch (PatientMergedException e) {
throw new WebApplicationException(errResponse(e.getMessage(), Response.Status.FORBIDDEN));
} catch (Exception e) {
throw new WebApplicationException(errResponseAsTextPlain(exceptionAsString(e), Response.Status.INTERNAL_SERVER_ERROR));
}
}
use of org.dcm4chee.arc.conf.ArchiveAEExtension in project dcm4chee-arc-light by dcm4che.
the class PamRS method updateCharset.
@POST
@Path("/patients/charset/{charset}")
public Response updateCharset(@Pattern(regexp = "ISO_IR 100|ISO_IR 101|ISO_IR 109|ISO_IR 110|ISO_IR 144|ISO_IR 127|ISO_IR 126|ISO_IR 138|ISO_IR 148|ISO_IR 13|ISO_IR 166|ISO_IR 192|GB18030|GBK") @PathParam("charset") String charset, @QueryParam("test") @Pattern(regexp = "true|false") @DefaultValue("false") String test) {
ArchiveAEExtension arcAE = getArchiveAE();
boolean update = !Boolean.parseBoolean(test);
int updated = 0;
List<IDWithIssuer> failures = new ArrayList<>();
try {
QueryAttributes queryAttrs = new QueryAttributes(uriInfo, null);
Attributes queryKeys = queryAttrs.getQueryKeys();
CriteriaQuery<AttributesBlob> query = queryService.createPatientAttributesQuery(queryParam(arcAE.getApplicationEntity(), false), queryKeys);
int limit = arcAE.getArchiveDeviceExtension().getUpdateCharsetFetchSize();
int offset = 0;
List<AttributesBlob> blobs = patientService.queryWithOffsetAndLimit(query, offset, limit);
if (blobs.isEmpty()) {
return Response.status(Response.Status.NO_CONTENT).build();
}
for (; ; ) {
for (AttributesBlob blob : blobs) {
Attributes attrs = blob.getAttributes();
if (charset.equals(attrs.getString(Tag.SpecificCharacterSet)))
continue;
attrs.setSpecificCharacterSet(charset);
blob.setAttributes(attrs);
if (attrs.equals(AttributesBlob.decodeAttributes(blob.getEncodedAttributes(), null))) {
if (update)
patientService.merge(blob);
updated++;
} else {
failures.add(IDWithIssuer.pidOf(attrs));
}
}
if (blobs.size() < limit)
break;
offset += blobs.size();
}
if (updated > 0)
rsForward.forward(RSOperation.UpdateCharset, arcAE, null, request);
return updateCharsetResponse(updated, failures).build();
} catch (Exception e) {
return errResponseAsTextPlain(exceptionAsString(e), Response.Status.INTERNAL_SERVER_ERROR);
}
}
Aggregations