diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java index 7a7d04c2483..721dccad006 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java @@ -104,24 +104,33 @@ public class ReferenceParam extends BaseParam /*implements IQueryParameterType*/ void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) { String q = theQualifier; String resourceType = null; + boolean skipSetValue = false; if (isNotBlank(q)) { if (q.startsWith(":")) { int nextIdx = q.indexOf('.'); if (nextIdx != -1) { resourceType = q.substring(1, nextIdx); myChain = q.substring(nextIdx + 1); + // type is explicitly defined so use it + myId.setParts(null, resourceType, theValue, null); + skipSetValue = true; } else { resourceType = q.substring(1); } } else if (q.startsWith(".")) { myChain = q.substring(1); + // type not defined but this is a chain, so treat value as opaque + myId.setParts(null, null, theValue, null); + skipSetValue = true; } } - setValue(theValue); + if (!skipSetValue) { + setValue(theValue); - if (isNotBlank(resourceType) && isBlank(getResourceType())) { - setValue(resourceType + '/' + theValue); + if (isNotBlank(resourceType) && isBlank(getResourceType())) { + setValue(resourceType + '/' + theValue); + } } } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/param/ReferenceParamTest.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/param/ReferenceParamTest.java index e6c108a1951..a61aa706ac2 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/param/ReferenceParamTest.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/param/ReferenceParamTest.java @@ -19,9 +19,61 @@ public class ReferenceParamTest { rp.setValueAsQueryToken(ourCtx, null, null, "Location/123"); assertEquals("Location", rp.getResourceType()); assertEquals("123", rp.getIdPart()); + assertEquals("Location/123", rp.getValue()); assertEquals(null, rp.getQueryParameterQualifier()); } + + @Test + public void testWithResourceType_AbsoluteUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, null, "http://a.b/c/d/e"); + assertEquals("d", rp.getResourceType()); + assertEquals("e", rp.getIdPart()); + assertEquals("http://a.b/c/d/e", rp.getValue()); + assertEquals(null, rp.getQueryParameterQualifier()); + + } + + @Test + public void testWithNoResourceTypeAsQualifierAndChain() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ".name", "FOO"); + assertEquals(null, rp.getResourceType()); + assertEquals("FOO", rp.getIdPart()); + assertEquals("FOO", rp.getValue()); + assertEquals(".name", rp.getQueryParameterQualifier()); + assertEquals("name", rp.getChain()); + + } + + @Test + public void testWithNoResourceTypeAsQualifierAndChain_RelativeUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ".name", "Patient/1233"); + assertEquals(null, rp.getResourceType()); + assertEquals("Patient/1233", rp.getIdPart()); + assertEquals("Patient/1233", rp.getValue()); + assertEquals(".name", rp.getQueryParameterQualifier()); + assertEquals("name", rp.getChain()); + + } + + @Test + public void testWithNoResourceTypeAsQualifierAndChain_AbsoluteUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ".name", "http://something.strange/a/b/c"); + assertEquals(null, rp.getResourceType()); + assertEquals("http://something.strange/a/b/c", rp.getIdPart()); + assertEquals("http://something.strange/a/b/c", rp.getValue()); + assertEquals(".name", rp.getQueryParameterQualifier()); + assertEquals("name", rp.getChain()); + + } @Test public void testWithResourceTypeAsQualifier() { @@ -30,6 +82,34 @@ public class ReferenceParamTest { rp.setValueAsQueryToken(ourCtx, null, ":Location", "123"); assertEquals("Location", rp.getResourceType()); assertEquals("123", rp.getIdPart()); + assertEquals("Location/123", rp.getValue()); + assertEquals(null, rp.getQueryParameterQualifier()); + + } + + // TODO: verify this behavior is correct. If type is explicitly specified (i.e. :Location), should it be + // an error if it gets overriden by the resourceType in the url? + @Test + public void testWithResourceTypeAsQualifier_RelativeUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ":Location", "Patient/123"); + assertEquals("Patient", rp.getResourceType()); + assertEquals("123", rp.getIdPart()); + assertEquals("Patient/123", rp.getValue()); + assertEquals(null, rp.getQueryParameterQualifier()); + + } + + // TODO: verify this behavior is correct. Same case as testWithResourceTypeAsQualifier_RelativeUrl() + @Test + public void testWithResourceTypeAsQualifier_AbsoluteUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ":Location", "http://a.b/c/d/e"); + assertEquals("d", rp.getResourceType()); + assertEquals("e", rp.getIdPart()); + assertEquals("http://a.b/c/d/e", rp.getValue()); assertEquals(null, rp.getQueryParameterQualifier()); } @@ -42,11 +122,51 @@ public class ReferenceParamTest { rp.setValueAsQueryToken(ourCtx, null, ":Location.name", "FOO"); assertEquals("Location", rp.getResourceType()); assertEquals("FOO", rp.getIdPart()); + assertEquals("Location/FOO", rp.getValue()); assertEquals(":Location.name", rp.getQueryParameterQualifier()); assertEquals("name", rp.getChain()); } + @Test + public void testWithResourceTypeAsQualifierAndChain_IdentifierUrlAndValue() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ":Patient.identifier", "http://hey.there/a/b|123"); + assertEquals("Patient", rp.getResourceType()); + assertEquals("http://hey.there/a/b|123", rp.getIdPart()); + assertEquals("Patient/http://hey.there/a/b|123", rp.getValue()); + assertEquals(":Patient.identifier", rp.getQueryParameterQualifier()); + assertEquals("identifier", rp.getChain()); + + } + + @Test + public void testWithResourceTypeAsQualifierAndChain_IdentifierUrlOnly() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ":Patient.identifier", "http://hey.there/a/b|"); + assertEquals("Patient", rp.getResourceType()); + assertEquals("http://hey.there/a/b|", rp.getIdPart()); + assertEquals("Patient/http://hey.there/a/b|", rp.getValue()); + assertEquals(":Patient.identifier", rp.getQueryParameterQualifier()); + assertEquals("identifier", rp.getChain()); + + } + + @Test + public void testWithResourceTypeAsQualifierAndChain_ValueOnlyNoUrl() { + + ReferenceParam rp = new ReferenceParam(); + rp.setValueAsQueryToken(ourCtx, null, ":Patient.identifier", "|abc"); + assertEquals("Patient", rp.getResourceType()); + assertEquals("|abc", rp.getIdPart()); + assertEquals("Patient/|abc", rp.getValue()); + assertEquals(":Patient.identifier", rp.getQueryParameterQualifier()); + assertEquals("identifier", rp.getChain()); + + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest();