diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java index 008b7fb3e0d..864f8e8b6e9 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java @@ -305,11 +305,16 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype, */IIdTy b.append(myResourceType); } - if (b.length() > 0) { + if (b.length() > 0 && isNotBlank(myUnqualifiedId)) { + b.append('/'); + } + + if (isNotBlank(myUnqualifiedId)) { + b.append(myUnqualifiedId); + } else if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); } - b.append(myUnqualifiedId); if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); b.append(Constants.PARAM_HISTORY); @@ -527,7 +532,21 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype, */IIdTy if (typeIndex == -1) { myResourceType = theValue.substring(0, idIndex); } else { - myResourceType = theValue.substring(typeIndex + 1, idIndex); + if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) { + typeIndex = theValue.indexOf('/', typeIndex + 1); + } + if (typeIndex >= idIndex) { + // e.g. http://example.org/foo + // 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id. + // Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly + // recreate the url + myResourceType = myUnqualifiedId; + myUnqualifiedId = null; + super.setValue(null); + myHaveComponentParts = true; + } else { + myResourceType = theValue.substring(typeIndex + 1, idIndex); + } if (typeIndex > 4) { myBaseUrl = theValue.substring(0, typeIndex); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java index 5209106280d..174b7d3ed81 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java @@ -197,8 +197,16 @@ public class ResourceLink implements Serializable { public void setTargetResourceUrl(IIdType theTargetResourceUrl) { Validate.isTrue(theTargetResourceUrl.hasBaseUrl()); Validate.isTrue(theTargetResourceUrl.hasResourceType()); - Validate.isTrue(theTargetResourceUrl.hasIdPart()); - + + if (theTargetResourceUrl.hasIdPart()) { + // do nothing + } else { + // Must have set an url like http://example.org/something + // We treat 'something' as the resource type because of fix for #659. Prior to #659 fix, 'something' was + // treated as the id and 'example.org' was treated as the resource type + // TODO: log a warning? + } + myTargetResourceType = theTargetResourceUrl.getResourceType(); myTargetResourceUrl = theTargetResourceUrl.getValue(); } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/primitive/IdDtTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/primitive/IdDtTest.java index ea55c68199d..96ba0396143 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/primitive/IdDtTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/primitive/IdDtTest.java @@ -84,7 +84,38 @@ public class IdDtTest { assertEquals("foo/_history/2", id.withVersion("2").getValue()); } - + @Test + public void testBaseUrlFoo1() { + IdDt id = new IdDt("http://my.org/foo"); + assertEquals("http://my.org/foo", id.getValueAsString()); + assertEquals(null, id.getIdPart()); + assertEquals("foo", id.toUnqualified().getValueAsString()); + assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("foo", id.getResourceType()); + assertEquals("http://my.org", id.getBaseUrl()); + + assertEquals("Patient", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue()); + } + + @Test + public void testBaseUrlFoo2() { + IdDt id = new IdDt("http://my.org/a/b/c/foo"); + assertEquals("http://my.org/a/b/c/foo", id.getValueAsString()); + assertEquals("foo", id.getIdPart()); + assertEquals("c/foo", id.toUnqualified().getValueAsString()); + assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("c", id.getResourceType()); + assertEquals("http://my.org/a/b", id.getBaseUrl()); + + assertEquals("Patient/foo", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue()); + } + @Test public void testDetectIsIdPartValid() { assertTrue(new IdDt("0").isIdPartValid()); diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/model/IdType.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/model/IdType.java index 8a6df569886..f5e4ee31a06 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/model/IdType.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/model/IdType.java @@ -358,11 +358,16 @@ public final class IdType extends UriType implements IPrimitiveType, IId b.append(myResourceType); } - if (b.length() > 0) { + if (b.length() > 0 && isNotBlank(myUnqualifiedId)) { + b.append('/'); + } + + if (isNotBlank(myUnqualifiedId)) { + b.append(myUnqualifiedId); + } else if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); } - b.append(myUnqualifiedId); if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); b.append("_history"); @@ -554,7 +559,21 @@ public final class IdType extends UriType implements IPrimitiveType, IId if (typeIndex == -1) { myResourceType = theValue.substring(0, idIndex); } else { - myResourceType = theValue.substring(typeIndex + 1, idIndex); + if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) { + typeIndex = theValue.indexOf('/', typeIndex + 1); + } + if (typeIndex >= idIndex) { + // e.g. http://example.org/foo + // 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id. + // Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly + // recreate the url + myResourceType = myUnqualifiedId; + myUnqualifiedId = null; + super.setValue(null); + myHaveComponentParts = true; + } else { + myResourceType = theValue.substring(typeIndex + 1, idIndex); + } if (typeIndex > 4) { myBaseUrl = theValue.substring(0, typeIndex); diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/IdTypeDstu2_1Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/IdTypeDstu2_1Test.java index acfeec4ae3e..674be996406 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/IdTypeDstu2_1Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/IdTypeDstu2_1Test.java @@ -92,6 +92,37 @@ public class IdTypeDstu2_1Test { assertEquals("foo/_history/2", id.withVersion("2").getValue()); } + @Test + public void testBaseUrlFoo1() { + IdType id = new IdType("http://my.org/foo"); + assertEquals("http://my.org/foo", id.getValueAsString()); + assertEquals(null, id.getIdPart()); + assertEquals("foo", id.toUnqualified().getValueAsString()); + assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("foo", id.getResourceType()); + assertEquals("http://my.org", id.getBaseUrl()); + + assertEquals("Patient", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue()); + } + + @Test + public void testBaseUrlFoo2() { + IdType id = new IdType("http://my.org/a/b/c/foo"); + assertEquals("http://my.org/a/b/c/foo", id.getValueAsString()); + assertEquals("foo", id.getIdPart()); + assertEquals("c/foo", id.toUnqualified().getValueAsString()); + assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("c", id.getResourceType()); + assertEquals("http://my.org/a/b", id.getBaseUrl()); + + assertEquals("Patient/foo", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue()); + } @Test public void testDetectLocal() { diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java index 1d25182fcb3..0fc2799411f 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java @@ -1876,6 +1876,26 @@ public class JsonParserDstu2_1Test { Assert.assertThat(message, containsString("contained")); } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @AfterClass diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2_1Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2_1Test.java index 529aad2e195..e3448b0df70 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2_1Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2_1Test.java @@ -100,6 +100,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.After; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -2738,6 +2739,26 @@ public class XmlParserDstu2_1Test { } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseResourceReferenceDtTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseResourceReferenceDtTest.java index 7bc4c9cb508..0ed6e6b85fe 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseResourceReferenceDtTest.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseResourceReferenceDtTest.java @@ -142,7 +142,7 @@ public class BaseResourceReferenceDtTest { new ResourceReferenceDt("http://foo/123123").loadResource(client); fail(); } catch (DataFormatException e) { - assertEquals("Unknown resource name \"foo\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage()); + assertEquals("Unknown resource name \"123123\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage()); } try { diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java index 87287c83271..bda50214d84 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java @@ -2043,4 +2043,24 @@ public class JsonParserDstu2Test { assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addUndeclaredExtension(false, "x1").setValue(new ResourceReferenceDt(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getUndeclaredExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((ResourceReferenceDt) extlst.get(0).getValue()).getReference().getValue()); + } } diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java index dc6e02c882f..d112f1d3073 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java @@ -33,6 +33,7 @@ import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -2853,6 +2854,26 @@ public class XmlParserDstu2Test { assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addUndeclaredExtension(false, "x1").setValue(new ResourceReferenceDt(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getUndeclaredExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((ResourceReferenceDt) extlst.get(0).getValue()).getReference().getValue()); + } @AfterClass public static void afterClassClearContext() { diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java index 02535643be3..530d9dfa284 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java @@ -357,11 +357,16 @@ public final class IdType extends UriType implements IPrimitiveType, IId b.append(myResourceType); } - if (b.length() > 0) { + if (b.length() > 0 && isNotBlank(myUnqualifiedId)) { + b.append('/'); + } + + if (isNotBlank(myUnqualifiedId)) { + b.append(myUnqualifiedId); + } else if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); } - b.append(myUnqualifiedId); if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); b.append("_history"); @@ -553,7 +558,21 @@ public final class IdType extends UriType implements IPrimitiveType, IId if (typeIndex == -1) { myResourceType = theValue.substring(0, idIndex); } else { - myResourceType = theValue.substring(typeIndex + 1, idIndex); + if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) { + typeIndex = theValue.indexOf('/', typeIndex + 1); + } + if (typeIndex >= idIndex) { + // e.g. http://example.org/foo + // 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id. + // Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly + // recreate the url + myResourceType = myUnqualifiedId; + myUnqualifiedId = null; + super.setValue(null); + myHaveComponentParts = true; + } else { + myResourceType = theValue.substring(typeIndex + 1, idIndex); + } if (typeIndex > 4) { myBaseUrl = theValue.substring(0, typeIndex); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/model/IdTypeDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/model/IdTypeDstu3Test.java index f21a09e6850..330e0dba256 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/model/IdTypeDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/model/IdTypeDstu3Test.java @@ -92,6 +92,38 @@ public class IdTypeDstu3Test { assertEquals("foo/_history/2", id.withVersion("2").getValue()); } + @Test + public void testBaseUrlFoo1() { + IdType id = new IdType("http://my.org/foo"); + assertEquals("http://my.org/foo", id.getValueAsString()); + assertEquals(null, id.getIdPart()); + assertEquals("foo", id.toUnqualified().getValueAsString()); + assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("foo", id.getResourceType()); + assertEquals("http://my.org", id.getBaseUrl()); + + assertEquals("Patient", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue()); + } + + @Test + public void testBaseUrlFoo2() { + IdType id = new IdType("http://my.org/a/b/c/foo"); + assertEquals("http://my.org/a/b/c/foo", id.getValueAsString()); + assertEquals("foo", id.getIdPart()); + assertEquals("c/foo", id.toUnqualified().getValueAsString()); + assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("c", id.getResourceType()); + assertEquals("http://my.org/a/b", id.getBaseUrl()); + + assertEquals("Patient/foo", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue()); + } + @Test public void testDetectLocal() { IdType id; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java index ab3e464b5d7..585096dd508 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java @@ -2430,6 +2430,26 @@ public class JsonParserDstu3Test { assertTrue(result.isSuccessful()); } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java index 831bc8afc1c..ba6aae1a51f 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java @@ -3323,6 +3323,26 @@ public class XmlParserDstu3Test { } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IdType.java b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IdType.java index 5239236c4ec..06b82519282 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IdType.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IdType.java @@ -384,11 +384,16 @@ public final class IdType extends UriType implements IPrimitiveType, IId b.append(myResourceType); } - if (b.length() > 0) { + if (b.length() > 0 && isNotBlank(myUnqualifiedId)) { + b.append('/'); + } + + if (isNotBlank(myUnqualifiedId)) { + b.append(myUnqualifiedId); + } else if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); } - b.append(myUnqualifiedId); if (isNotBlank(myUnqualifiedVersionId)) { b.append('/'); b.append("_history"); @@ -571,7 +576,21 @@ public final class IdType extends UriType implements IPrimitiveType, IId if (typeIndex == -1) { myResourceType = theValue.substring(0, idIndex); } else { - myResourceType = theValue.substring(typeIndex + 1, idIndex); + if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) { + typeIndex = theValue.indexOf('/', typeIndex + 1); + } + if (typeIndex >= idIndex) { + // e.g. http://example.org/foo + // 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id. + // Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly + // recreate the url + myResourceType = myUnqualifiedId; + myUnqualifiedId = null; + super.setValue(null); + myHaveComponentParts = true; + } else { + myResourceType = theValue.substring(typeIndex + 1, idIndex); + } if (typeIndex > 4) { myBaseUrl = theValue.substring(0, typeIndex); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/IdTypeTest.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/IdTypeTest.java index ed2893da6b2..4065965c348 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/IdTypeTest.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/IdTypeTest.java @@ -83,7 +83,55 @@ public class IdTypeTest { assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart()); } - + + @Test + public void testNormal() { + IdType id = new IdType("foo"); + assertEquals("foo", id.getValueAsString()); + assertEquals("foo", id.getIdPart()); + assertEquals("foo", id.toUnqualified().getValueAsString()); + assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals(null, id.getResourceType()); + assertEquals(null, id.getBaseUrl()); + + assertEquals("Patient/foo", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("foo/_history/2", id.withVersion("2").getValue()); + } + + @Test + public void testBaseUrlFoo1() { + IdType id = new IdType("http://my.org/foo"); + assertEquals("http://my.org/foo", id.getValueAsString()); + assertEquals(null, id.getIdPart()); + assertEquals("foo", id.toUnqualified().getValueAsString()); + assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("foo", id.getResourceType()); + assertEquals("http://my.org", id.getBaseUrl()); + + assertEquals("Patient", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue()); + } + + @Test + public void testBaseUrlFoo2() { + IdType id = new IdType("http://my.org/a/b/c/foo"); + assertEquals("http://my.org/a/b/c/foo", id.getValueAsString()); + assertEquals("foo", id.getIdPart()); + assertEquals("c/foo", id.toUnqualified().getValueAsString()); + assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString()); + assertEquals(null, id.getVersionIdPart()); + assertEquals("c", id.getResourceType()); + assertEquals("http://my.org/a/b", id.getBaseUrl()); + + assertEquals("Patient/foo", id.withResourceType("Patient").getValue()); + assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue()); + assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue()); + } + @Test public void testDetermineBase() { diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java index b14af83f968..a8eb1a6c333 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java @@ -63,6 +63,7 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.junit.After; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.xml.sax.SAXException; @@ -1383,6 +1384,26 @@ public class JsonParserHl7OrgDstu2Test { } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtension(); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @ResourceDef(name = "Patient") public static class MyPatientWithOneDeclaredAddressExtension extends Patient { diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java index a090236f69d..46802d8d3cb 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java @@ -65,6 +65,7 @@ import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.junit.After; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -1790,6 +1791,26 @@ public class XmlParserHl7OrgDstu2Test { } + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtension(); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + @BeforeClass public static void beforeClass() { XMLUnit.setIgnoreAttributeOrder(true);