Additional progress for ancestor/descendant filters; only ancestor/in remains.

This commit is contained in:
Diederik Muylwyk 2019-09-25 21:36:36 -04:00
parent 7c5cf9f1f4
commit 4f7db37d8e
2 changed files with 82 additions and 19 deletions

View File

@ -876,9 +876,12 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
handleFilterLoincParentChild(theQb, theBool, theFilter); handleFilterLoincParentChild(theQb, theBool, theFilter);
break; break;
case "ancestor": case "ancestor":
isCodeSystemLoingOrThrowInvalidRequestException(theSystem, theFilter.getProperty());
handleFilterLoincAncestor(theSystem, theQb, theBool, theFilter);
break;
case "descendant": case "descendant":
isCodeSystemLoingOrThrowInvalidRequestException(theSystem, theFilter.getProperty()); isCodeSystemLoingOrThrowInvalidRequestException(theSystem, theFilter.getProperty());
handleFilterLoincAncestorDescendant(theQb, theBool, theFilter); handleFilterLoincDescendant(theSystem, theQb, theBool, theFilter);
break; break;
case "copyright": case "copyright":
isCodeSystemLoingOrThrowInvalidRequestException(theSystem, theFilter.getProperty()); isCodeSystemLoingOrThrowInvalidRequestException(theSystem, theFilter.getProperty());
@ -942,11 +945,14 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
} }
private void handleFilterLoincParentChild(QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) { private void handleFilterLoincParentChild(QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
if (theFilter.getOp() == ValueSet.FilterOperator.EQUAL) { switch (theFilter.getOp()) {
case EQUAL:
addLoincFilterParentChildEqual(theBool, theFilter.getProperty(), theFilter.getValue()); addLoincFilterParentChildEqual(theBool, theFilter.getProperty(), theFilter.getValue());
} else if (theFilter.getOp() == ValueSet.FilterOperator.IN) { break;
case IN:
addLoincFilterParentChildIn(theBool, theFilter); addLoincFilterParentChildIn(theBool, theFilter);
} else { break;
default:
throw new InvalidRequestException("Don't know how to handle op=" + theFilter.getOp() + " on property " + theFilter.getProperty()); throw new InvalidRequestException("Don't know how to handle op=" + theFilter.getOp() + " on property " + theFilter.getProperty());
} }
} }
@ -970,28 +976,81 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
return new Term(TermConceptPropertyFieldBridge.CONCEPT_FIELD_PROPERTY_PREFIX + theProperty, theValue); return new Term(TermConceptPropertyFieldBridge.CONCEPT_FIELD_PROPERTY_PREFIX + theProperty, theValue);
} }
private void handleFilterLoincAncestorDescendant(QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) { private void handleFilterLoincAncestor(String theSystem, QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
if (theFilter.getOp() == ValueSet.FilterOperator.EQUAL) { switch (theFilter.getOp()) {
addLoincFilterAncestorDescendantEqual(theBool, theFilter.getProperty(), theFilter.getValue()); case EQUAL:
} else if (theFilter.getOp() == ValueSet.FilterOperator.IN) { addLoincFilterAncestorEqual(theSystem, theQb, theBool, theFilter);
addLoincFilterAncestorDescendantIn(theBool, theFilter); break;
} else { case IN:
addLoincFilterAncestorIn(theSystem, theQb, theBool, theFilter);
break;
default:
throw new InvalidRequestException("Don't know how to handle op=" + theFilter.getOp() + " on property " + theFilter.getProperty()); throw new InvalidRequestException("Don't know how to handle op=" + theFilter.getOp() + " on property " + theFilter.getProperty());
} }
} }
private void addLoincFilterAncestorDescendantEqual(BooleanJunction<?> theBool, String theProperty, String theValue) { private void addLoincFilterAncestorEqual(String theSystem, QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
logFilteringValueOnProperty(theValue, theProperty); TermConcept code = findCode(theSystem, theFilter.getValue())
// FIXME: DM 2019-09-25 - Filter with op=EQUAL on ancestor/descendant .orElseThrow(() -> new InvalidRequestException("Invalid filter criteria - code does not exist: {" + theSystem + "}" + theFilter.getValue()));
logFilteringValueOnProperty(theFilter.getValue(), theFilter.getProperty());
theBool.must(theQb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
} }
private void addLoincFilterAncestorDescendantIn(BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) { private void addLoincFilterAncestorIn(String theSystem, QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
String[] values = theFilter.getValue().split(","); String[] values = theFilter.getValue().split(",");
List<Term> terms = new ArrayList<>(); List<Term> terms = new ArrayList<>();
for (String value : values) { for (String value : values) {
logFilteringValueOnProperty(value, theFilter.getProperty()); logFilteringValueOnProperty(value, theFilter.getProperty());
// FIXME: DM 2019-09-25 - Filter with op=IN on ancestor/descendant // FIXME: DM 2019-09-25 - Filter with op=IN on ancestor
} }
theBool.must(new TermsQuery(terms));
}
private void handleFilterLoincDescendant(String theSystem, QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
switch (theFilter.getOp()) {
case EQUAL:
addLoincFilterDescendantEqual(theSystem, theBool, theFilter);
break;
case IN:
addLoincFilterDescendantIn(theSystem, theQb, theBool, theFilter);
break;
default:
throw new InvalidRequestException("Don't know how to handle op=" + theFilter.getOp() + " on property " + theFilter.getProperty());
}
}
private void addLoincFilterDescendantEqual(String theSystem, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
addLoincFilterDescendantEqual(theSystem, theBool, theFilter.getProperty(), theFilter.getValue());
}
private void addLoincFilterDescendantEqual(String theSystem, BooleanJunction<?> theBool, String theProperty, String theValue) {
List<Term> terms = getDescendantTerms(theSystem, theProperty, theValue);
theBool.must(new TermsQuery(terms));
}
private void addLoincFilterDescendantIn(String theSystem, QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {
String[] values = theFilter.getValue().split(",");
List<Term> terms = new ArrayList<>();
for (String value : values) {
terms.addAll(getDescendantTerms(theSystem, theFilter.getProperty(), value));
}
theBool.must(new TermsQuery(terms));
}
private List<Term> getDescendantTerms(String theSystem, String theProperty, String theValue) {
List<Term> retVal = new ArrayList<>();
TermConcept code = findCode(theSystem, theValue)
.orElseThrow(() -> new InvalidRequestException("Invalid filter criteria - code does not exist: {" + theSystem + "}" + theValue));
String[] parentPids = code.getParentPidsAsString().split(" ");
for (String parentPid : parentPids) {
retVal.add(new Term("myId", parentPid));
}
logFilteringValueOnProperty(theValue, theProperty);
return retVal;
} }
private void handleFilterLoincCopyright(QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) { private void handleFilterLoincCopyright(QueryBuilder theQb, BooleanJunction<?> theBool, ValueSet.ConceptSetFilterComponent theFilter) {

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
import ca.uhn.fhir.jpa.entity.TermCodeSystem; import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -150,6 +151,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
LOINC_URI, LOINC_URI,
code2.getCode(), code2.getCode(),
code2.getDisplay()); code2.getDisplay());
code1.addChild(code2, TermConceptParentChildLink.RelationshipTypeEnum.ISA);
cs.getConcepts().add(code1); cs.getConcepts().add(code1);
code2.addPropertyString("SYSTEM", "Ser"); code2.addPropertyString("SYSTEM", "Ser");
@ -164,11 +166,13 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
LOINC_URI, LOINC_URI,
code3.getCode(), code3.getCode(),
code3.getDisplay()); code3.getDisplay());
code2.addChild(code3, TermConceptParentChildLink.RelationshipTypeEnum.ISA);
code2.addPropertyCoding( code2.addPropertyCoding(
"child", "child",
LOINC_URI, LOINC_URI,
code4.getCode(), code4.getCode(),
code4.getDisplay()); code4.getDisplay());
code2.addChild(code4, TermConceptParentChildLink.RelationshipTypeEnum.ISA);
cs.getConcepts().add(code2); cs.getConcepts().add(code2);
code3.addPropertyString("SYSTEM", "Ser"); code3.addPropertyString("SYSTEM", "Ser");