From d86e9d28b8abf5e7d66fae828374807c2d3fe322 Mon Sep 17 00:00:00 2001 From: Troy Biesterfeld Date: Fri, 19 Mar 2021 11:31:30 -0500 Subject: [PATCH] Issue #1323 - Extract :of-type parameter as internal composite Signed-off-by: Troy Biesterfeld --- .../jdbc/impl/FHIRPersistenceJDBCImpl.java | 6 +- .../util/JDBCParameterBuildingVisitor.java | 91 ++++++++++++++-- .../test/util/ParameterExtractionTest.java | 103 ++++++++++++------ .../com/ibm/fhir/search/SearchConstants.java | 7 +- 4 files changed, 156 insertions(+), 51 deletions(-) diff --git a/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java b/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java index 53e5b87e580..2333261de50 100644 --- a/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java +++ b/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java @@ -1409,7 +1409,7 @@ private List extractSearchParameters(Resource fhirResou // Of course, that would require adding extension-search-params to the Registry which would require the Registry to be tenant-aware. // SearchParameter compSP = FHIRRegistry.getInstance().getResource(component.getDefinition().getValue(), SearchParameter.class); SearchParameter compSP = SearchUtil.getSearchParameter(p.getResourceType(), component.getDefinition()); - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(compSP); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(p.getResourceType(), compSP); FHIRPathNode node = nodes.iterator().next(); if (nodes.size() > 1 ) { // TODO: support component expressions that result in multiple nodes @@ -1455,7 +1455,6 @@ private List extractSearchParameters(Resource fhirResou ExtractedParameterValue componentParam = parameters.get(0); // override the component parameter name with the composite parameter name componentParam.setName(SearchUtil.makeCompositeSubCode(code, componentParam.getName())); - componentParam.setResourceType(p.getResourceType()); componentParam.setBase(p.getBase()); p.addComponent(componentParam); } else if (node.isSystemValue()){ @@ -1498,7 +1497,7 @@ private List extractSearchParameters(Resource fhirResou } } } else { // ! SearchParamType.COMPOSITE.equals(sp.getType()) - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(sp); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(fhirResource.getClass().getSimpleName(), sp); for (FHIRPathNode value : values) { @@ -1542,7 +1541,6 @@ private List extractSearchParameters(Resource fhirResou // retrieve the list of parameters built from all the FHIRPathElementNode values List parameters = parameterBuilder.getResult(); for (ExtractedParameterValue p : parameters) { - p.setResourceType(fhirResource.getClass().getSimpleName()); allParameters.add(p); if (log.isLoggable(Level.FINE)) { log.fine("Extracted Parameter '" + p.getName() + "' from Resource."); diff --git a/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/util/JDBCParameterBuildingVisitor.java b/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/util/JDBCParameterBuildingVisitor.java index 7846623c64a..38c09556204 100644 --- a/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/util/JDBCParameterBuildingVisitor.java +++ b/fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/util/JDBCParameterBuildingVisitor.java @@ -47,6 +47,7 @@ import com.ibm.fhir.model.util.ModelSupport; import com.ibm.fhir.model.visitor.DefaultVisitor; import com.ibm.fhir.model.visitor.Visitable; +import com.ibm.fhir.persistence.jdbc.dto.CompositeParmVal; import com.ibm.fhir.persistence.jdbc.dto.DateParmVal; import com.ibm.fhir.persistence.jdbc.dto.ExtractedParameterValue; import com.ibm.fhir.persistence.jdbc.dto.LocationParmVal; @@ -62,6 +63,7 @@ import com.ibm.fhir.search.util.ReferenceUtil; import com.ibm.fhir.search.util.ReferenceValue; import com.ibm.fhir.search.util.ReferenceValue.ReferenceType; +import com.ibm.fhir.search.util.SearchUtil; /** * This class is the JDBC persistence layer implementation for transforming @@ -90,6 +92,7 @@ public class JDBCParameterBuildingVisitor extends DefaultVisitor { private static final Timestamp LARGEST_TIMESTAMP = Timestamp.from( ZonedDateTime.parse("9999-12-31T23:59:59.999999Z").toInstant()); + private final String resourceType; // We only need the SearchParameter type and code, so just store those directly as members private final String searchParamCode; private final SearchParamType searchParamType; @@ -99,8 +102,9 @@ public class JDBCParameterBuildingVisitor extends DefaultVisitor { */ private List result; - public JDBCParameterBuildingVisitor(SearchParameter searchParameter) { + public JDBCParameterBuildingVisitor(String resourceType, SearchParameter searchParameter) { super(false); + this.resourceType = resourceType; this.searchParamCode = searchParameter.getCode().getValue(); this.searchParamType = searchParameter.getType(); @@ -131,10 +135,11 @@ public boolean visit(String elementName, int elementIndex, Visitable visitable) @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Boolean _boolean) { if (_boolean.hasValue()) { - TokenParmVal p = new TokenParmVal(); if (!TOKEN.equals(searchParamType)) { throw invalidComboException(searchParamType, _boolean); } + TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueSystem("http://terminology.hl7.org/CodeSystem/special-values"); if (_boolean.getValue()) { @@ -150,10 +155,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Canonical canonical) { if (canonical.hasValue()) { - StringParmVal p = new StringParmVal(); if (!REFERENCE.equals(searchParamType) && !URI.equals(searchParamType)) { throw invalidComboException(searchParamType, canonical); } + StringParmVal p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(canonical.getValue()); result.add(p); @@ -164,10 +170,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Code code) { if (code.hasValue()) { - TokenParmVal p = new TokenParmVal(); if (!TOKEN.equals(searchParamType)) { throw invalidComboException(searchParamType, code); } + TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueSystem(ModelSupport.getSystem(code)); p.setValueCode(code.getValue()); @@ -179,10 +186,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Date date) { if (date.hasValue()) { - DateParmVal p = new DateParmVal(); if (!DATE.equals(searchParamType)) { throw invalidComboException(searchParamType, date); } + DateParmVal p = new DateParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); setDateValues(p, date); result.add(p); @@ -193,10 +201,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.DateTime dateTime) { if (dateTime.hasValue()) { - DateParmVal p = new DateParmVal(); if (!DATE.equals(searchParamType)) { throw invalidComboException(searchParamType, dateTime); } + DateParmVal p = new DateParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); setDateValues(p, dateTime); result.add(p); @@ -207,10 +216,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Decimal decimal) { if (decimal.hasValue()) { - NumberParmVal p = new NumberParmVal(); if (!NUMBER.equals(searchParamType)) { throw invalidComboException(searchParamType, decimal); } + NumberParmVal p = new NumberParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); BigDecimal value = decimal.getValue(); p.setValueNumber(value); @@ -224,10 +234,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Id id) { if (id.hasValue()) { - TokenParmVal p = new TokenParmVal(); if (!TOKEN.equals(searchParamType)) { throw invalidComboException(searchParamType, id); } + TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueCode(id.getValue()); result.add(p); @@ -238,10 +249,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Instant instant) { if (instant.hasValue()) { - DateParmVal p = new DateParmVal(); if (!DATE.equals(searchParamType)) { throw invalidComboException(searchParamType, instant); } + DateParmVal p = new DateParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); Timestamp t = generateTimestamp(instant.getValue().toInstant()); p.setValueDateStart(t); @@ -254,10 +266,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhi @Override public boolean visit(java.lang.String elementName, int elementIndex, com.ibm.fhir.model.type.Integer integer) { if (integer.hasValue()) { - NumberParmVal p = new NumberParmVal(); if (!NUMBER.equals(searchParamType)) { throw invalidComboException(searchParamType, integer); } + NumberParmVal p = new NumberParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); BigDecimal value = new BigDecimal(integer.getValue()); p.setValueNumber(value); @@ -273,11 +286,13 @@ public boolean visit(String elementName, int elementIndex, com.ibm.fhir.model.ty if (value.hasValue()) { if (STRING.equals(searchParamType)) { StringParmVal p = new StringParmVal(); + p.setResourceType(resourceType); p.setValueString(value.getValue()); p.setName(searchParamCode); result.add(p); } else if (TOKEN.equals(searchParamType)) { TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setValueCode(value.getValue()); p.setName(searchParamCode); result.add(p); @@ -299,11 +314,13 @@ public boolean visit(String elementName, int elementIndex, Uri uri) { // not strings. if (REFERENCE.equals(this.searchParamType)) { TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueCode(uri.getValue()); result.add(p); } else { StringParmVal p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(uri.getValue()); result.add(p); @@ -326,42 +343,49 @@ public boolean visit(java.lang.String elementName, int elementIndex, Address add } for (com.ibm.fhir.model.type.String aLine : address.getLine()) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(aLine.getValue()); result.add(p); } if (address.getCity() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getCity().getValue()); result.add(p); } if (address.getDistrict() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getDistrict().getValue()); result.add(p); } if (address.getState() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getState().getValue()); result.add(p); } if (address.getCountry() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getCountry().getValue()); result.add(p); } if (address.getPostalCode() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getPostalCode().getValue()); result.add(p); } if (address.getText() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(address.getText().getValue()); result.add(p); @@ -383,10 +407,11 @@ public boolean visit(java.lang.String elementName, int elementIndex, CodeableCon @Override public boolean visit(java.lang.String elementName, int elementIndex, Coding coding) { if (coding.getCode() != null && coding.getCode().hasValue()) { - TokenParmVal p = new TokenParmVal(); if (!TOKEN.equals(searchParamType)) { throw invalidComboException(searchParamType, coding); } + TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueCode(coding.getCode().getValue()); if (coding.getSystem() != null) { @@ -404,6 +429,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, ContactPoin throw invalidComboException(searchParamType, contactPoint); } TokenParmVal telecom = new TokenParmVal(); + telecom.setResourceType(resourceType); telecom.setName(searchParamCode); telecom.setValueCode(contactPoint.getValue().getValue()); result.add(telecom); @@ -420,30 +446,35 @@ public boolean visit(java.lang.String elementName, int elementIndex, HumanName h if (humanName.getFamily() != null) { // family is just a string in R4 (not a list) p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(humanName.getFamily().getValue()); result.add(p); } for (com.ibm.fhir.model.type.String given : humanName.getGiven()) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(given.getValue()); result.add(p); } for (com.ibm.fhir.model.type.String prefix : humanName.getPrefix()) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(prefix.getValue()); result.add(p); } for (com.ibm.fhir.model.type.String suffix : humanName.getSuffix()) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(suffix.getValue()); result.add(p); } if (humanName.getText() != null) { p = new StringParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueString(humanName.getText().getValue()); result.add(p); @@ -458,6 +489,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Money money } if (money != null && money.getValue() != null && money.getValue().getValue() != null) { QuantityParmVal p = new QuantityParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueNumber(money.getValue().getValue()); if (money.getCurrency() != null) { @@ -478,6 +510,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Period peri return false; } DateParmVal p = new DateParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); if (period.getStart() == null || period.getStart().getValue() == null) { p.setValueDateStart(SMALLEST_TIMESTAMP); @@ -510,6 +543,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Quantity qu // see https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=19597 if (quantity.getCode() != null && quantity.getCode().hasValue()) { QuantityParmVal p = new QuantityParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueNumber(value); p.setValueNumberLow(valueLow); @@ -525,6 +559,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Quantity qu // No need to save a second parameter value if the display unit matches the coded unit if (quantity.getCode() == null || !displayUnit.equals(quantity.getCode().getValue())) { QuantityParmVal p = new QuantityParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); p.setValueNumber(value); p.setValueNumberLow(valueLow); @@ -544,6 +579,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Range range } // The parameter isn't added unless either low or high holds a value QuantityParmVal p = new QuantityParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); if (range.getLow() != null && range.getLow().getValue() != null && range.getLow().getValue().getValue() != null) { @@ -587,12 +623,42 @@ public boolean visit(java.lang.String elementName, int elementIndex, Identifier } if (identifier != null && identifier.getValue() != null) { TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); if (identifier.getSystem() != null) { p.setValueSystem(identifier.getSystem().getValue()); } p.setValueCode(identifier.getValue().getValue()); result.add(p); + if (identifier.getType() != null) { + for (Coding typeCoding : identifier.getType().getCoding()) { + if (typeCoding.getCode() != null && typeCoding.getCode().hasValue()) { + // Create as composite parm since type/value are correlated for the :of-type modifier + CompositeParmVal cp = new CompositeParmVal(); + cp.setResourceType(resourceType); + cp.setName(searchParamCode + SearchConstants.OF_TYPE_MODIFIER_SUFFIX); + + // type + p = new TokenParmVal(); + p.setResourceType(cp.getResourceType()); + p.setName(SearchUtil.makeCompositeSubCode(cp.getName(), SearchConstants.OF_TYPE_MODIFIER_COMPONENT_TYPE)); + if (typeCoding.getSystem() != null) { + p.setValueSystem(typeCoding.getSystem().getValue()); + } + p.setValueCode(typeCoding.getCode().getValue()); + cp.addComponent(p); + + // value + p = new TokenParmVal(); + p.setResourceType(cp.getResourceType()); + p.setName(SearchUtil.makeCompositeSubCode(cp.getName(), SearchConstants.OF_TYPE_MODIFIER_COMPONENT_VALUE)); + p.setValueCode(identifier.getValue().getValue()); + cp.addComponent(p); + + result.add(cp); + } + } + } } return false; } @@ -611,6 +677,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Reference r ReferenceValue refValue = ReferenceUtil.createReferenceValueFrom(reference, baseUrl); if (refValue.getType() != ReferenceType.LOGICAL && refValue.getType() != ReferenceType.INVALID && refValue.getType() != ReferenceType.DISPLAY_ONLY) { ReferenceParmVal p = new ReferenceParmVal(); + p.setResourceType(resourceType); p.setRefValue(refValue); p.setName(searchParamCode); result.add(p); @@ -618,6 +685,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Reference r Identifier identifier = reference.getIdentifier(); if (identifier != null && identifier.getValue() != null) { TokenParmVal p = new TokenParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode + SearchConstants.IDENTIFIER_MODIFIER_SUFFIX); if (identifier.getSystem() != null) { p.setValueSystem(identifier.getSystem().getValue()); @@ -660,6 +728,7 @@ public boolean visit(java.lang.String elementName, int elementIndex, Timing timi @Override public boolean visit(java.lang.String elementName, int elementIndex, Location.Position position) { LocationParmVal p = new LocationParmVal(); + p.setResourceType(resourceType); p.setName(searchParamCode); // The following code ensures that the lat/lon is only added when there is a pair. diff --git a/fhir-persistence-jdbc/src/test/java/com/ibm/fhir/persistence/jdbc/test/util/ParameterExtractionTest.java b/fhir-persistence-jdbc/src/test/java/com/ibm/fhir/persistence/jdbc/test/util/ParameterExtractionTest.java index 0c24951802e..32862a1a8d9 100644 --- a/fhir-persistence-jdbc/src/test/java/com/ibm/fhir/persistence/jdbc/test/util/ParameterExtractionTest.java +++ b/fhir-persistence-jdbc/src/test/java/com/ibm/fhir/persistence/jdbc/test/util/ParameterExtractionTest.java @@ -56,6 +56,7 @@ import com.ibm.fhir.model.type.code.ResourceType; import com.ibm.fhir.model.type.code.SearchParamType; import com.ibm.fhir.persistence.exception.FHIRPersistenceProcessorException; +import com.ibm.fhir.persistence.jdbc.dto.CompositeParmVal; import com.ibm.fhir.persistence.jdbc.dto.DateParmVal; import com.ibm.fhir.persistence.jdbc.dto.ExtractedParameterValue; import com.ibm.fhir.persistence.jdbc.dto.NumberParmVal; @@ -65,6 +66,7 @@ import com.ibm.fhir.persistence.jdbc.dto.TokenParmVal; import com.ibm.fhir.persistence.jdbc.util.JDBCParameterBuildingVisitor; import com.ibm.fhir.search.SearchConstants; +import com.ibm.fhir.search.util.SearchUtil; /** * Tests all valid combinations of search paramter types and data types @@ -113,7 +115,7 @@ public void setSystemTimeZone() { @Test public void testBoolean() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); com.ibm.fhir.model.type.Boolean.TRUE.accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -133,13 +135,13 @@ public void testCanonical() throws FHIRPersistenceProcessorException { Canonical canonical = Canonical.of(SAMPLE_URI); List params; - parameterBuilder = new JDBCParameterBuildingVisitor(referenceSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, referenceSearchParam); canonical.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); assertEquals(((StringParmVal) params.get(0)).getValueString(), SAMPLE_URI); - parameterBuilder = new JDBCParameterBuildingVisitor(uriSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, uriSearchParam); canonical.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -154,7 +156,7 @@ public void testCanonical_null() throws FHIRPersistenceProcessorException { @Test public void testCode() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); Code.of(SAMPLE_STRING).accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -168,7 +170,7 @@ public void testCode_null() throws FHIRPersistenceProcessorException { @Test public void testDate() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Date.of("2016").accept(parameterBuilder); List params = parameterBuilder.getResult(); for (ExtractedParameterValue param : params) { @@ -185,7 +187,7 @@ public void testDate_null() throws FHIRPersistenceProcessorException { @Test public void testDateTime() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); DateTime.of("2016-01-01T10:10:10.1+04:00").accept(parameterBuilder); List params = parameterBuilder.getResult(); for (ExtractedParameterValue param : params) { @@ -200,7 +202,7 @@ public void testDateTime_null() throws FHIRPersistenceProcessorException { @Test public void testDecimal() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(numberSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, numberSearchParam); Decimal.of(99.99).accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -216,7 +218,7 @@ public void testDecimal_null() throws FHIRPersistenceProcessorException { @Test public void testId() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); Id.of("x").accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -230,7 +232,7 @@ public void testId_null() throws FHIRPersistenceProcessorException { @Test public void testInstant() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Instant now = Instant.now(ZoneOffset.UTC); now.accept(parameterBuilder); List params = parameterBuilder.getResult(); @@ -245,7 +247,7 @@ public void testInstant_null() throws FHIRPersistenceProcessorException { @Test public void testInteger() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(numberSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, numberSearchParam); Integer.of(13).accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -263,13 +265,13 @@ public void testString() throws FHIRPersistenceProcessorException { com.ibm.fhir.model.type.String stringVal = string(SAMPLE_STRING); List params; - parameterBuilder = new JDBCParameterBuildingVisitor(stringSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, stringSearchParam); stringVal.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); assertEquals(((StringParmVal) params.get(0)).getValueString(), SAMPLE_STRING); - parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); stringVal.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -288,13 +290,13 @@ public void testUri() throws FHIRPersistenceProcessorException { Uri uri = Uri.of(SAMPLE_URI); List params; - parameterBuilder = new JDBCParameterBuildingVisitor(referenceSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, referenceSearchParam); uri.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); assertEquals(((TokenParmVal) params.get(0)).getValueCode(), SAMPLE_URI); - parameterBuilder = new JDBCParameterBuildingVisitor(uriSearchParam); + parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, uriSearchParam); uri.accept(parameterBuilder); params = parameterBuilder.getResult(); assertEquals(params.size(), 1, "Number of extracted parameters"); @@ -308,7 +310,7 @@ public void testUri_null() throws FHIRPersistenceProcessorException { } private void assertNullValueReturnsNoParameters(SearchParameter sp, Element.Builder builder) { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(sp); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, sp); builder.extension(SAMPLE_EXTENSION).build().accept(parameterBuilder); List params = parameterBuilder.getResult(); assertEquals(params.size(), 0, "Number of extracted parameters"); @@ -317,7 +319,7 @@ private void assertNullValueReturnsNoParameters(SearchParameter sp, Element.Buil @Test public void testAddress() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(stringSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, stringSearchParam); Address.builder() .line(string("4025 S. Miami Blvd.")) //0 .city(string("Durham")) //1 @@ -342,7 +344,7 @@ public void testAddress_null() throws FHIRPersistenceProcessorException { @Test public void testAge() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Age.builder() .value(Decimal.of(1)) .system(Uri.of(UNITSOFMEASURE)) @@ -365,7 +367,7 @@ public void testAge_null() throws FHIRPersistenceProcessorException { @Test public void testCodeableConcept() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); CodeableConcept.builder() .coding(Coding.builder().code(Code.of("a")).system(Uri.of(SAMPLE_URI)).build()) .coding(Coding.builder().code(Code.of("b")).system(Uri.of(SAMPLE_URI)).build()) @@ -389,7 +391,7 @@ public void testCodeableConcept_null() throws FHIRPersistenceProcessorException @Test public void testCoding() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); Coding.builder() .code(Code.of(SAMPLE_STRING)) .system(Uri.of(SAMPLE_URI)) @@ -408,7 +410,7 @@ public void testCoding_null() throws FHIRPersistenceProcessorException { @Test public void testContactPoint() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); ContactPoint.builder() .system(ContactPointSystem.PHONE) .value(string("5558675309")) @@ -426,7 +428,7 @@ public void testContactPoint_null() throws FHIRPersistenceProcessorException { @Test public void testDuration() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Duration.builder() .value(Decimal.of(1)) .system(Uri.of(UNITSOFMEASURE)) @@ -447,7 +449,7 @@ public void testDuration_null() throws FHIRPersistenceProcessorException { @Test public void testHumanName() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(stringSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, stringSearchParam); HumanName.builder() .family(string("Simpson")) //0 .given(string("Nick")) //1 @@ -472,16 +474,47 @@ public void testHumanName_null() throws FHIRPersistenceProcessorException { @Test public void testIdentifier() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(tokenSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, tokenSearchParam); Identifier.builder() + .type(CodeableConcept.builder() + .coding(Coding.builder().code(Code.of("codea")).system(Uri.of("systema")).build()) + .coding(Coding.builder().code(Code.of("codeb")).build()) + .build()) .system(Uri.of(SAMPLE_URI)) .value(string("abc123")) .build() .accept(parameterBuilder); List params = parameterBuilder.getResult(); - assertEquals(params.size(), 1, "Number of extracted parameters"); + assertEquals(params.size(), 3, "Number of extracted parameters"); assertEquals(((TokenParmVal) params.get(0)).getValueSystem(), SAMPLE_URI); assertEquals(((TokenParmVal) params.get(0)).getValueCode(), "abc123"); + + // Check composite parameters extracted for :of-type modifier + String compositeCode = SEARCH_PARAM_CODE_VALUE + SearchConstants.OF_TYPE_MODIFIER_SUFFIX; + + CompositeParmVal cParmVal = (CompositeParmVal) params.get(1); + assertEquals(cParmVal.getName(), compositeCode); + assertEquals(cParmVal.getComponent().size(), 2, "Number of extracted components"); + TokenParmVal tokenParmVal = (TokenParmVal) cParmVal.getComponent().get(0); + assertEquals(tokenParmVal.getName(), SearchUtil.makeCompositeSubCode(compositeCode, SearchConstants.OF_TYPE_MODIFIER_COMPONENT_TYPE)); + assertEquals(tokenParmVal.getValueSystem(), "systema"); + assertEquals(tokenParmVal.getValueCode(), "codea"); + tokenParmVal = (TokenParmVal) cParmVal.getComponent().get(1); + assertEquals(tokenParmVal.getName(), SearchUtil.makeCompositeSubCode(compositeCode, SearchConstants.OF_TYPE_MODIFIER_COMPONENT_VALUE)); + assertEquals(tokenParmVal.getValueSystem(), TokenParmVal.DEFAULT_TOKEN_SYSTEM); + assertEquals(tokenParmVal.getValueCode(), "abc123"); + + cParmVal = (CompositeParmVal) params.get(2); + assertEquals(cParmVal.getName(), compositeCode); + assertEquals(cParmVal.getComponent().size(), 2, "Number of extracted components"); + tokenParmVal = (TokenParmVal) cParmVal.getComponent().get(0); + assertEquals(tokenParmVal.getName(), SearchUtil.makeCompositeSubCode(compositeCode, SearchConstants.OF_TYPE_MODIFIER_COMPONENT_TYPE)); + assertEquals(tokenParmVal.getValueSystem(), TokenParmVal.DEFAULT_TOKEN_SYSTEM); + assertEquals(tokenParmVal.getValueCode(), "codeb"); + tokenParmVal = (TokenParmVal) cParmVal.getComponent().get(1); + assertEquals(tokenParmVal.getName(), SearchUtil.makeCompositeSubCode(compositeCode, SearchConstants.OF_TYPE_MODIFIER_COMPONENT_VALUE)); + assertEquals(tokenParmVal.getValueSystem(), TokenParmVal.DEFAULT_TOKEN_SYSTEM); + assertEquals(tokenParmVal.getValueCode(), "abc123"); } @Test @@ -491,7 +524,7 @@ public void testIdentifier_null() throws FHIRPersistenceProcessorException { @Test public void testMoney() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Money.builder() .currency(Code.of("USD")) .value(Decimal.of(100)) @@ -510,7 +543,7 @@ public void testMoney_null() throws FHIRPersistenceProcessorException { @Test public void testPeriod() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Period.builder() .start(DateTime.of(SAMPLE_DATE_START)) .end(DateTime.of(SAMPLE_DATE_END)) @@ -524,7 +557,7 @@ public void testPeriod() throws FHIRPersistenceProcessorException { @Test public void testPeriod_nullStart() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Period.builder() .end(DateTime.of(SAMPLE_DATE_END)) .build() @@ -536,7 +569,7 @@ public void testPeriod_nullStart() throws FHIRPersistenceProcessorException { @Test public void testPeriod_nullEnd() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Period.builder() .start(DateTime.of(SAMPLE_DATE_START)) .build() @@ -553,7 +586,7 @@ public void testPeriod_null() throws FHIRPersistenceProcessorException { @Test public void testQuantity() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Quantity.builder() .value(Decimal.of(1)) .system(Uri.of(UNITSOFMEASURE)) @@ -574,7 +607,7 @@ public void testQuantity_null() throws FHIRPersistenceProcessorException { @Test public void testRange() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Range range = Range.builder() .low(SimpleQuantity.builder() .code(Code.of(SAMPLE_UNIT)) @@ -601,7 +634,7 @@ public void testRange() throws FHIRPersistenceProcessorException { @Test public void testRange_nullHigh() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Range range = Range.builder() .low(SimpleQuantity.builder() .code(Code.of(SAMPLE_UNIT)) @@ -622,7 +655,7 @@ public void testRange_nullHigh() throws FHIRPersistenceProcessorException { @Test public void testRange_nullLow() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(quantitySearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, quantitySearchParam); Range range = Range.builder() .high(SimpleQuantity.builder() .code(Code.of(SAMPLE_UNIT)) @@ -648,7 +681,7 @@ public void testRange_null() throws FHIRPersistenceProcessorException { @Test public void testReference() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(referenceSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, referenceSearchParam); Reference.builder() .reference(string(SAMPLE_REF)) .identifier(Identifier.builder() @@ -674,7 +707,7 @@ public void testReference_null() throws FHIRPersistenceProcessorException { @Test public void testTimingBounds() throws FHIRPersistenceProcessorException { - JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); + JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); Period period = Period.builder() .start(DateTime.of(SAMPLE_DATE_START)) .end(DateTime.of(SAMPLE_DATE_END)) @@ -698,7 +731,7 @@ public void testTiming_null() throws FHIRPersistenceProcessorException { // Timing doesn't currently extract from "events" // @Test // public void testTimingEvents() throws FHIRPersistenceProcessorException { -// JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(dateSearchParam); +// JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(SAMPLE_REF_RESOURCE_TYPE, dateSearchParam); // Timing.builder() // .event(DateTime.of(SAMPLE_DATE_START)) // .event(DateTime.of(SAMPLE_DATE_END)) diff --git a/fhir-search/src/main/java/com/ibm/fhir/search/SearchConstants.java b/fhir-search/src/main/java/com/ibm/fhir/search/SearchConstants.java index debbd1698e4..7461567f3d8 100644 --- a/fhir-search/src/main/java/com/ibm/fhir/search/SearchConstants.java +++ b/fhir-search/src/main/java/com/ibm/fhir/search/SearchConstants.java @@ -99,7 +99,12 @@ private SearchConstants() { // Extracted search parameter suffix for :identifier modifier public static final String IDENTIFIER_MODIFIER_SUFFIX = ":identifier"; - + + // Extracted search parameter suffixes for :of-type modifier + public static final String OF_TYPE_MODIFIER_SUFFIX = ":of-type"; + public static final String OF_TYPE_MODIFIER_COMPONENT_TYPE = "type"; + public static final String OF_TYPE_MODIFIER_COMPONENT_VALUE = "value"; + // set as unmodifiable public static final Set SEARCH_RESULT_PARAMETER_NAMES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(SORT, COUNT, PAGE, INCLUDE, REVINCLUDE, ELEMENTS, SUMMARY, TOTAL)));