Skip to content

Commit

Permalink
Fix #4587 : QIDO-RS Search for Studies : Multiple records returned if…
Browse files Browse the repository at this point in the history
… PatientID used in query filter, wherein patient record has same PatientID value on root dataset as well as in items of Other Patient IDs Sequence, but has differing issuers
  • Loading branch information
vrindanayak committed Oct 23, 2024
1 parent 5b72b6d commit e600188
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,18 @@ private boolean orderPersonName(Path<org.dcm4chee.arc.entity.PersonName> personN
return true;
}

public <T, Z> void patientIDPredicate(
List<Predicate> predicates, CriteriaQuery<T> q, From<Z, Patient> patient, IDWithIssuer[] pids) {
Subquery<PatientID> sq = q.subquery(PatientID.class);
Root<PatientID> patientIdentifier = sq.from(PatientID.class);
List<Predicate> y = new ArrayList<>();
patIDPredicate(y, pids, patientIdentifier);
if (!y.isEmpty()) {
y.add(cb.equal(patientIdentifier.get(PatientID_.patient), patient));
predicates.add(cb.exists(sq.select(patientIdentifier).where(y.toArray(new Predicate[0]))));
}
}

private <X> void patIDWithoutIssuerPredicate(List<Predicate> predicates, From<X, PatientID> patientID, IDWithIssuer[] pids) {
predicates.add(patientID.get(PatientID_.localNamespaceEntityID).isNull());
predicates.add(patientID.get(PatientID_.universalEntityID).isNull());
Expand All @@ -363,22 +375,6 @@ private <X> void patIDWithoutIssuerPredicate(List<Predicate> predicates, From<X,
predicates.add(cb.or(idPredicates.toArray(new Predicate[0])));
}

private <Z> void patientIDWithoutIssuerPredicate(List<Predicate> predicates,
From<Z, Patient> patient,
IDWithIssuer[] pids) {
patIDWithoutIssuerPredicate(predicates, patient.join(Patient_.patientIDs), pids);
}

public <Z> void patientIDPredicate(List<Predicate> predicates,
From<Z, Patient> patient,
IDWithIssuer[] pids) {
patIDPredicate(predicates, pids, patient.join(Patient_.patientIDs));
}

private <Z> void patientIDIssuerPredicate(List<Predicate> predicates, From<Z, Patient> patient, Issuer issuer) {
patIDIssuerPredicate(predicates, issuer, patient.join(Patient_.patientIDs));
}

private <X> void patIDPredicate(List<Predicate> predicates, IDWithIssuer[] pids, From<X, PatientID> patientID) {
List<Predicate> idPredicates = new ArrayList<>(pids.length);
for (IDWithIssuer pid : pids)
Expand Down Expand Up @@ -410,20 +406,6 @@ public <T> List<Predicate> patientPredicates(CriteriaQuery<T> q,
return predicates;
}

public <T> List<Predicate> patientIDPredicates(CriteriaQuery<T> q,
Root<PatientID> patientID, Join<PatientID, Patient> patient, IDWithIssuer[] pids, Issuer issuer,
Attributes keys, QueryParam queryParam) {
List<Predicate> predicates = new ArrayList<>();
if (queryParam.isWithoutIssuer())
patIDWithoutIssuerPredicate(predicates, patientID, pids);
else if (!QueryBuilder.isUniversalMatching(pids))
patIDPredicate(predicates, pids, patientID);
else if (!QueryBuilder.isUniversalMatching(issuer))
patIDIssuerPredicate(predicates, issuer, patientID);
patientLevelPredicates2(predicates, q, patient, pids, issuer, keys, queryParam, QueryRetrieveLevel2.PATIENT);
return predicates;
}

public <T> List<Predicate> studyPredicates(CriteriaQuery<T> q,
From<Study, Patient> patient, Root<Study> study,
IDWithIssuer[] pids, Issuer issuer, Attributes keys, QueryParam queryParam,
Expand Down Expand Up @@ -582,17 +564,38 @@ private <T, Z> void patientLevelPredicates(List<Predicate> predicates, CriteriaQ
if (patient == null)
return;

Subquery<PatientID> sq = q.subquery(PatientID.class);
Root<PatientID> patientIdentifier = sq.from(PatientID.class);
List<Predicate> y = new ArrayList<>();
if (queryParam.isWithoutIssuer())
patIDWithoutIssuerPredicate(y, patientIdentifier, pids);
else if (!QueryBuilder.isUniversalMatching(pids))
patIDPredicate(y, pids, patientIdentifier);
else if (!QueryBuilder.isUniversalMatching(issuer))
patIDIssuerPredicate(y, issuer, patientIdentifier);
if (!y.isEmpty()) {
y.add(cb.equal(patientIdentifier.get(PatientID_.patient), patient));
predicates.add(cb.exists(sq.select(patientIdentifier).where(y.toArray(new Predicate[0]))));
}
patientLevelPredicates2(predicates, q, patient, keys, queryParam, queryRetrieveLevel);
}

public <T> List<Predicate> patientIDPredicates(
CriteriaQuery<T> q, Root<PatientID> patientID, Join<PatientID, Patient> patient, IDWithIssuer[] pids, Issuer issuer,
Attributes keys, QueryParam queryParam) {
List<Predicate> predicates = new ArrayList<>();
if (queryParam.isWithoutIssuer())
patientIDWithoutIssuerPredicate(predicates, patient, pids);
patIDWithoutIssuerPredicate(predicates, patientID, pids);
else if (!QueryBuilder.isUniversalMatching(pids))
patientIDPredicate(predicates, patient, pids);
patIDPredicate(predicates, pids, patientID);
else if (!QueryBuilder.isUniversalMatching(issuer))
patientIDIssuerPredicate(predicates, patient, issuer);
patientLevelPredicates2(predicates, q, patient, pids, issuer, keys, queryParam, queryRetrieveLevel);
patIDIssuerPredicate(predicates, issuer, patientID);
patientLevelPredicates2(predicates, q, patient, keys, queryParam, QueryRetrieveLevel2.PATIENT);
return predicates;
}

private <T, Z> void patientLevelPredicates2(List<Predicate> predicates, CriteriaQuery<T> q,
From<Z, Patient> patient, IDWithIssuer[] pids, Issuer issuer, Attributes keys, QueryParam queryParam,
From<Z, Patient> patient, Attributes keys, QueryParam queryParam,
QueryRetrieveLevel2 queryRetrieveLevel) {
if (queryRetrieveLevel == QueryRetrieveLevel2.PATIENT) {
if (queryParam.isMerged())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public LocationQuery(EntityManager em, CriteriaBuilder cb, RetrieveContext ctx,
} else {
QueryBuilder builder = new QueryBuilder(cb);
if (!QueryBuilder.isUniversalMatching(ctx.getPatientIDs())) {
builder.patientIDPredicate(predicates, study.join(Study_.patient), ctx.getPatientIDs());
builder.patientIDPredicate(predicates, q, study.join(Study_.patient), ctx.getPatientIDs());
}
builder.accessControl(predicates, study, ctx.getAccessControlIDs());
builder.seriesAccessControl(predicates, series, ctx.getAccessControlIDs());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ private void queryLocationsFromMetadata(RetrieveContext ctx, CriteriaBuilder cb,
List<Predicate> predicates = new ArrayList<>();
QueryBuilder builder = new QueryBuilder(cb);
if (!QueryBuilder.isUniversalMatching(ctx.getPatientIDs())) {
builder.patientIDPredicate(predicates, study.join(Study_.patient), ctx.getPatientIDs());
builder.patientIDPredicate(predicates, q, study.join(Study_.patient), ctx.getPatientIDs());
}
builder.accessControl(predicates, study, ctx.getAccessControlIDs());
builder.seriesAccessControl(predicates, series, ctx.getAccessControlIDs());
Expand Down

0 comments on commit e600188

Please sign in to comment.