From 599bbe236c81fc050f421bced67578fdcafb9371 Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Mon, 23 Jan 2017 18:42:46 -0500
Subject: [PATCH] Work on #544
---
.../ca/uhn/fhir/model/primitive/IdDt.java | 165 ++++++++---------
.../java/ca/uhn/fhir/parser/JsonParser.java | 2 +-
.../java/ca/uhn/fhir/parser/ParserState.java | 25 ++-
.../java/ca/uhn/fhir/parser/XmlParser.java | 2 +-
.../hl7/fhir/instance/model/api/IIdType.java | 31 ++++
.../ca/uhn/fhir/model/primitive/IdDtTest.java | 81 +++++++-
.../ca/uhn/fhir/parser/XmlParserTest.java | 4 +-
.../hl7/fhir/dstu2016may/model/IdType.java | 82 ++++-----
.../ca/uhn/fhir/model/IdTypeDstu2_1Test.java | 84 ++++++++-
.../fhir/parser/JsonParserDstu2_1Test.java | 62 +------
.../uhn/fhir/parser/JsonParserDstu2Test.java | 19 +-
.../java/org/hl7/fhir/dstu3/model/IdType.java | 78 ++++----
.../ca/uhn/fhir/model/IdTypeDstu3Test.java | 83 ++++++++-
.../uhn/fhir/parser/XmlParserDstu3Test.java | 16 ++
.../test/resources/bundle_ref_by_uuid_544.xml | 174 ++++++++++++++++++
15 files changed, 644 insertions(+), 264 deletions(-)
create mode 100644 hapi-fhir-structures-dstu3/src/test/resources/bundle_ref_by_uuid_544.xml
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 a942f74e5e6..6c888f6b92e 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
@@ -1,5 +1,6 @@
package ca.uhn.fhir.model.primitive;
+import static org.apache.commons.lang3.StringUtils.defaultString;
/*
* #%L
* HAPI FHIR - Core Library
@@ -10,7 +11,7 @@ package ca.uhn.fhir.model.primitive;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -52,7 +53,7 @@ import ca.uhn.fhir.util.UrlUtil;
* regex: [a-z-Z0-9\-\.]{1,36}
*
*/
-@DatatypeDef(name = "id", profileOf=StringDt.class)
+@DatatypeDef(name = "id", profileOf = StringDt.class)
public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
private String myBaseUrl;
@@ -106,9 +107,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Constructor
*
* @param theResourceType
- * The resource type (e.g. "Patient")
+ * The resource type (e.g. "Patient")
* @param theIdPart
- * The ID (e.g. "123")
+ * The ID (e.g. "123")
*/
public IdDt(String theResourceType, BigDecimal theIdPart) {
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
@@ -118,9 +119,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Constructor
*
* @param theResourceType
- * The resource type (e.g. "Patient")
+ * The resource type (e.g. "Patient")
* @param theIdPart
- * The ID (e.g. "123")
+ * The ID (e.g. "123")
*/
public IdDt(String theResourceType, Long theIdPart) {
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
@@ -130,9 +131,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Constructor
*
* @param theResourceType
- * The resource type (e.g. "Patient")
+ * The resource type (e.g. "Patient")
* @param theId
- * The ID (e.g. "123")
+ * The ID (e.g. "123")
*/
public IdDt(String theResourceType, String theId) {
this(theResourceType, theId, null);
@@ -142,11 +143,11 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Constructor
*
* @param theResourceType
- * The resource type (e.g. "Patient")
+ * The resource type (e.g. "Patient")
* @param theId
- * The ID (e.g. "123")
+ * The ID (e.g. "123")
* @param theVersionId
- * The version ID ("e.g. "456")
+ * The version ID ("e.g. "456")
*/
public IdDt(String theResourceType, String theId, String theVersionId) {
this(null, theResourceType, theId, theVersionId);
@@ -156,13 +157,13 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Constructor
*
* @param theBaseUrl
- * The server base URL (e.g. "http://example.com/fhir")
+ * The server base URL (e.g. "http://example.com/fhir")
* @param theResourceType
- * The resource type (e.g. "Patient")
+ * The resource type (e.g. "Patient")
* @param theId
- * The ID (e.g. "123")
+ * The ID (e.g. "123")
* @param theVersionId
- * The version ID ("e.g. "456")
+ * The version ID ("e.g. "456")
*/
public IdDt(String theBaseUrl, String theResourceType, String theId, String theVersionId) {
myBaseUrl = theBaseUrl;
@@ -202,34 +203,6 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
return getIdPartAsBigDecimal();
}
- private String determineLocalPrefix(String theValue) {
- if (theValue == null || theValue.isEmpty()) {
- return null;
- }
- if (theValue.startsWith("#")) {
- return "#";
- }
- int lastPrefix = -1;
- for (int i = 0; i < theValue.length(); i++) {
- char nextChar = theValue.charAt(i);
- if (nextChar == ':') {
- lastPrefix = i;
- } else if (!Character.isLetter(nextChar) || !Character.isLowerCase(nextChar)) {
- break;
- }
- }
- if (lastPrefix != -1) {
- String candidate = theValue.substring(0, lastPrefix + 1);
- if (candidate.startsWith("cid:") || candidate.startsWith("urn:")) {
- return candidate;
- } else {
- return null;
- }
- } else {
- return null;
- }
- }
-
@Override
public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdDt)) {
@@ -277,7 +250,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Returns the unqualified portion of this ID as a big decimal, or null
if the value is null
*
* @throws NumberFormatException
- * If the value is not a valid BigDecimal
+ * If the value is not a valid BigDecimal
*/
public BigDecimal getIdPartAsBigDecimal() {
String val = getIdPart();
@@ -291,7 +264,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Returns the unqualified portion of this ID as a {@link Long}, or null
if the value is null
*
* @throws NumberFormatException
- * If the value is not a valid Long
+ * If the value is not a valid Long
*/
@Override
public Long getIdPartAsLong() {
@@ -315,11 +288,11 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
@Override
public String getValue() {
if (super.getValue() == null && myHaveComponentParts) {
-
- if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) {
- return myBaseUrl + myUnqualifiedId;
+
+ if (isLocal() || isUrn()) {
+ return myUnqualifiedId;
}
-
+
StringBuilder b = new StringBuilder();
if (isNotBlank(myBaseUrl)) {
b.append(myBaseUrl);
@@ -448,18 +421,23 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
}
/**
- * Returns true
if the ID is a local reference (in other words, it begins with the '#' character)
+ * Returns true
if the ID is a local reference (in other words,
+ * it begins with the '#' character)
*/
@Override
public boolean isLocal() {
- return "#".equals(myBaseUrl);
+ return defaultString(myUnqualifiedId).startsWith("#");
+ }
+
+ private boolean isUrn() {
+ return defaultString(myUnqualifiedId).startsWith("urn:");
}
@Override
public boolean isVersionIdPartValidLong() {
return isValidLong(getVersionIdPart());
}
-
+
/**
* Copies the value from the given IdDt to this
IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
*/
@@ -468,6 +446,27 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
setValue(theId.getValue());
}
+ @Override
+ public IIdType setParts(String theBaseUrl, String theResourceType, String theIdPart, String theVersionIdPart) {
+ if (isNotBlank(theVersionIdPart)) {
+ Validate.notBlank(theResourceType, "If theVersionIdPart is populated, theResourceType and theIdPart must be populated");
+ Validate.notBlank(theIdPart, "If theVersionIdPart is populated, theResourceType and theIdPart must be populated");
+ }
+ if (isNotBlank(theBaseUrl) && isNotBlank(theIdPart)) {
+ Validate.notBlank(theResourceType, "If theBaseUrl is populated and theIdPart is populated, theResourceType must be populated");
+ }
+
+ setValue(null);
+
+ myBaseUrl = theBaseUrl;
+ myResourceType = theResourceType;
+ myUnqualifiedId = theIdPart;
+ myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionIdPart, null);
+ myHaveComponentParts = true;
+
+ return this;
+ }
+
/**
* Set the value
*
@@ -484,9 +483,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
// TODO: add validation
super.setValue(theValue);
myHaveComponentParts = false;
-
- String localPrefix = determineLocalPrefix(theValue);
-
+
if (StringUtils.isBlank(theValue)) {
myBaseUrl = null;
super.setValue(null);
@@ -495,14 +492,14 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
super.setValue(theValue);
- myBaseUrl = "#";
- myUnqualifiedId = theValue.substring(1);
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
- } else if (localPrefix != null) {
- myBaseUrl = localPrefix;
- myUnqualifiedId = theValue.substring(localPrefix.length());
+ } else if (theValue.startsWith("urn:")) {
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
@@ -567,24 +564,33 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
*/
@Override
public IdDt toUnqualified() {
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
+ }
return new IdDt(getResourceType(), getIdPart(), getVersionIdPart());
}
@Override
public IdDt toUnqualifiedVersionless() {
- if (isLocal()) {
- return toVersionless();
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
}
return new IdDt(getResourceType(), getIdPart());
}
@Override
public IdDt toVersionless() {
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
+ }
return new IdDt(getBaseUrl(), getResourceType(), getIdPart(), null);
}
@Override
public IdDt withResourceType(String theResourceName) {
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
+ }
return new IdDt(theResourceName, getIdPart(), getVersionIdPart());
}
@@ -593,13 +599,16 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* because IdDt can contain either a complete URL or a partial one (or even jut a simple ID), this method may be used to translate into a complete URL.
*
* @param theServerBase
- * The server base (e.g. "http://example.com/fhir")
+ * The server base (e.g. "http://example.com/fhir")
* @param theResourceType
- * The resource name (e.g. "Patient")
+ * The resource name (e.g. "Patient")
* @return A fully qualified URL for this ID (e.g. "http://example.com/fhir/Patient/1")
*/
@Override
public IdDt withServerBase(String theServerBase, String theResourceType) {
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
+ }
return new IdDt(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
}
@@ -607,12 +616,17 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID noted by theVersion.
*
* @param theVersion
- * The actual version string, e.g. "1"
+ * The actual version string, e.g. "1"
* @return A new instance of IdDt which is identical, but refers to the specific version of this resource ID noted by theVersion.
*/
+ @Override
public IdDt withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty");
+ if (isLocal() || isUrn()) {
+ return new IdDt(getValueAsString());
+ }
+
String existingValue = getValue();
int i = existingValue.indexOf(Constants.PARAM_HISTORY);
@@ -678,25 +692,4 @@ public class IdDt extends UriDt implements IPrimitiveDatatype, IIdType {
return theIdPart.toString();
}
- @Override
- public IIdType setParts(String theBaseUrl, String theResourceType, String theIdPart, String theVersionIdPart) {
- if (isNotBlank(theVersionIdPart)) {
- Validate.notBlank(theResourceType, "If theVersionIdPart is populated, theResourceType and theIdPart must be populated");
- Validate.notBlank(theIdPart, "If theVersionIdPart is populated, theResourceType and theIdPart must be populated");
- }
- if (isNotBlank(theBaseUrl) && isNotBlank(theIdPart)) {
- Validate.notBlank(theResourceType, "If theBaseUrl is populated and theIdPart is populated, theResourceType must be populated");
- }
-
- setValue(null);
-
- myBaseUrl = theBaseUrl;
- myResourceType = theResourceType;
- myUnqualifiedId = theIdPart;
- myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionIdPart, null);
- myHaveComponentParts = true;
-
- return this;
- }
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
index 6f8868c4f02..782907c977d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
@@ -347,7 +347,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
for (BundleEntry nextEntry : theBundle.getEntries()) {
theEventWriter.beginObject();
- if (nextEntry.getResource() != null && nextEntry.getResource().getId().getBaseUrl() != null) {
+ if (nextEntry.getResource() != null && isNotBlank(nextEntry.getResource().getIdElement().getValue()) && (nextEntry.getResource().getId().getBaseUrl() != null || nextEntry.getResource().getId().getValueAsString().startsWith("urn:"))) {
writeOptionalTagWithTextNode(theEventWriter, "fullUrl", nextEntry.getResource().getId().getValue());
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
index 6fc5a4b9736..9750f68f511 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
@@ -721,7 +721,6 @@ class ParserState {
myInstance = theInstance;
}
- @SuppressWarnings("unchecked")
@Override
public void wereBack() {
@@ -2090,17 +2089,32 @@ class ParserState {
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
if (bundle) {
+ FhirTerser t = myContext.newTerser();
+
+ Map idToResource = new HashMap();
+ if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
+ List entries = t.getValues(myInstance, "Bundle.entry", IBase.class);
+ for (IBase nextEntry : entries) {
+ IPrimitiveType> fullUrl = t.getSingleValueOrNull(nextEntry, "fullUrl", IPrimitiveType.class);
+ if (fullUrl != null && isNotBlank(fullUrl.getValueAsString())) {
+ IBaseResource resource = t.getSingleValueOrNull(nextEntry, "resource", IBaseResource.class);
+ if (resource != null) {
+ idToResource.put(fullUrl.getValueAsString(), resource);
+ }
+ }
+ }
+ }
+
/*
* Stitch together resource references
*/
- Map idToResource = new HashMap();
- FhirTerser t = myContext.newTerser();
List resources = t.getAllPopulatedChildElementsOfType(myInstance, IBaseResource.class);
for (IBaseResource next : resources) {
IIdType id = next.getIdElement();
if (id != null && id.isEmpty() == false) {
String resName = myContext.getResourceDefinition(next).getName();
- idToResource.put(id.withResourceType(resName).toUnqualifiedVersionless(), next);
+ IIdType idType = id.withResourceType(resName).toUnqualifiedVersionless();
+ idToResource.put(idType.getValueAsString(), next);
}
}
@@ -2108,7 +2122,8 @@ class ParserState {
List refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, IBaseReference.class);
for (IBaseReference nextRef : refs) {
if (nextRef.isEmpty() == false && nextRef.getReferenceElement() != null) {
- IBaseResource target = idToResource.get(nextRef.getReferenceElement().toUnqualifiedVersionless());
+ IIdType unqualifiedVersionless = nextRef.getReferenceElement().toUnqualifiedVersionless();
+ IBaseResource target = idToResource.get(unqualifiedVersionless.getValueAsString());
if (target != null) {
nextRef.setResource(target);
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
index a0fbff92853..19f402c0125 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
@@ -446,7 +446,7 @@ public class XmlParser extends BaseParser implements IParser {
writeBundleResourceLink(theEventWriter, "alternate", nextEntry.getLinkAlternate());
- if (nextEntry.getResource() != null && nextEntry.getResource().getId().getBaseUrl() != null) {
+ if (nextEntry.getResource() != null && isNotBlank(nextEntry.getResource().getIdElement().getValue()) && (nextEntry.getResource().getId().getBaseUrl() != null || nextEntry.getResource().getId().getValueAsString().startsWith("urn:"))) {
writeOptionalTagWithValue(theEventWriter, "fullUrl", nextEntry.getResource().getId().getValue());
}
diff --git a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java
index 9d370db1fbe..119ddb66e4e 100644
--- a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java
+++ b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java
@@ -130,10 +130,41 @@ public interface IIdType extends IPrimitiveType {
IIdType toVersionless();
+ /**
+ * Returns a copy of this object, but with a different {@link #getResourceType() resource type}
+ * (or if this object does not have a resource type currently, returns a copy of this object with
+ * the given resource type).
+ *
+ * Note that if this object represents a local reference (e.g. #foo
) or
+ * a URN (e.g. urn:oid:1.2.3.4
) this method will simply return a copy
+ * of this object with no modifications.
+ *
+ */
IIdType withResourceType(String theResName);
+ /**
+ * Returns a copy of this object, but with a different {@link #getResourceType() resource type}
+ * and {@link #getBaseUrl() base URL}
+ * (or if this object does not have a resource type currently, returns a copy of this object with
+ * the given server base and resource type).
+ *
+ * Note that if this object represents a local reference (e.g. #foo
) or
+ * a URN (e.g. urn:oid:1.2.3.4
) this method will simply return a copy
+ * of this object with no modifications.
+ *
+ */
IIdType withServerBase(String theServerBase, String theResourceName);
+ /**
+ * Returns a copy of this object, but with a different {@link #getVersionIdPart() version ID}
+ * (or if this object does not have a resource type currently, returns a copy of this object with
+ * the given version).
+ *
+ * Note that if this object represents a local reference (e.g. #foo
) or
+ * a URN (e.g. urn:oid:1.2.3.4
) this method will simply return a copy
+ * of this object with no modifications.
+ *
+ */
IIdType withVersion(String theVersion);
/**
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 100cec3ed74..ea55c68199d 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
@@ -20,6 +20,71 @@ public class IdDtTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdDtTest.class);
+ @Test
+ public void testUuid() {
+ IdDt id = new IdDt("urn:uuid:1234-5678");
+ assertEquals("urn:uuid:1234-5678", id.getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.getIdPart());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testOid() {
+ IdDt id = new IdDt("urn:oid:1.2.3.4");
+ assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.getIdPart());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testLocal() {
+ IdDt id = new IdDt("#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("#foo", id.withResourceType("Patient").getValue());
+ assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("#foo", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testNormal() {
+ IdDt id = new IdDt("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 testDetectIsIdPartValid() {
assertTrue(new IdDt("0").isIdPartValid());
@@ -60,16 +125,16 @@ public class IdDtTest {
@Test
public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("urn:uuid:", new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("cid:", new IdDt("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdDt("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("#", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
}
@@ -80,10 +145,10 @@ public class IdDtTest {
public void testComplicatedLocal() {
IdDt id = new IdDt("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal());
- assertEquals("#", id.getBaseUrl());
+ assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType());
assertNull(id.getVersionIdPart());
- assertEquals("Patient/cid:Patient-72/_history/1", id.getIdPart());
+ assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
}
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
index edd620a8cf3..12d87c133b6 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
@@ -561,8 +561,8 @@ public class XmlParserTest {
// Re-parse the bundle
patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
assertEquals("#1", patient.getManagingOrganization().getReference().getValue());
- assertEquals("#", patient.getManagingOrganization().getReference().getBaseUrl());
- assertEquals("1", patient.getManagingOrganization().getReference().getIdPart());
+ assertEquals(null, patient.getManagingOrganization().getReference().getBaseUrl());
+ assertEquals("#1", patient.getManagingOrganization().getReference().getIdPart());
assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource();
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 8204c31a3f5..8a6df569886 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
@@ -1,5 +1,7 @@
package org.hl7.fhir.dstu2016may.model;
+import static org.apache.commons.lang3.StringUtils.defaultString;
+
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
@@ -242,34 +244,6 @@ public final class IdType extends UriType implements IPrimitiveType, IId
return new IdType(getValue());
}
- private String determineLocalPrefix(String theValue) {
- if (theValue == null || theValue.isEmpty()) {
- return null;
- }
- if (theValue.startsWith("#")) {
- return "#";
- }
- int lastPrefix = -1;
- for (int i = 0; i < theValue.length(); i++) {
- char nextChar = theValue.charAt(i);
- if (nextChar == ':') {
- lastPrefix = i;
- } else if (!Character.isLetter(nextChar) || !Character.isLowerCase(nextChar)) {
- break;
- }
- }
- if (lastPrefix != -1) {
- String candidate = theValue.substring(0, lastPrefix + 1);
- if (candidate.startsWith("cid:") || candidate.startsWith("urn:")) {
- return candidate;
- } else {
- return null;
- }
- } else {
- return null;
- }
- }
-
@Override
public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdType)) {
@@ -368,8 +342,8 @@ public final class IdType extends UriType implements IPrimitiveType, IId
String retVal = super.getValue();
if (retVal == null && myHaveComponentParts) {
- if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) {
- return myBaseUrl + myUnqualifiedId;
+ if (isLocal() || isUrn()) {
+ return myUnqualifiedId;
}
StringBuilder b = new StringBuilder();
@@ -510,7 +484,11 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public boolean isLocal() {
- return "#".equals(myBaseUrl);
+ return defaultString(myUnqualifiedId).startsWith("#");
+ }
+
+ private boolean isUrn() {
+ return defaultString(myUnqualifiedId).startsWith("urn:");
}
@Override
@@ -536,8 +514,6 @@ public final class IdType extends UriType implements IPrimitiveType, IId
super.setValue(theValue);
myHaveComponentParts = false;
- String localPrefix = determineLocalPrefix(theValue);
-
if (StringUtils.isBlank(theValue)) {
myBaseUrl = null;
super.setValue(null);
@@ -545,15 +521,18 @@ public final class IdType extends UriType implements IPrimitiveType, IId
myUnqualifiedVersionId = null;
myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
- super.setValue(theValue);
- myBaseUrl = "#";
- myUnqualifiedId = theValue.substring(1);
- myUnqualifiedVersionId = null;
- myResourceType = null;
- myHaveComponentParts = true;
- } else if (localPrefix != null) {
- myBaseUrl = localPrefix;
- myUnqualifiedId = theValue.substring(localPrefix.length());
+ super.setValue(theValue);
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
+ myUnqualifiedVersionId = null;
+ myResourceType = null;
+ myHaveComponentParts = true;
+ } else if (theValue.startsWith("urn:")) {
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
+ myUnqualifiedVersionId = null;
+ myResourceType = null;
+ myHaveComponentParts = true;
} else {
int vidIndex = theValue.indexOf("/_history/");
int idIndex;
@@ -618,21 +597,33 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public IdType toUnqualified() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getResourceType(), getIdPart(), getVersionIdPart());
}
@Override
public IdType toUnqualifiedVersionless() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getResourceType(), getIdPart());
}
@Override
public IdType toVersionless() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null);
}
@Override
public IdType withResourceType(String theResourceName) {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(theResourceName, getIdPart(), getVersionIdPart());
}
@@ -652,6 +643,9 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public IdType withServerBase(String theServerBase, String theResourceType) {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
}
@@ -667,6 +661,10 @@ public final class IdType extends UriType implements IPrimitiveType, IId
public IdType withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty");
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
+
String existingValue = getValue();
int i = existingValue.indexOf("_history");
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 97a84ec0cce..acfeec4ae3e 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
@@ -28,6 +28,70 @@ public class IdTypeDstu2_1Test {
TestUtil.clearAllStaticFieldsForUnitTest();
}
+ @Test
+ public void testUuid() {
+ IdType id = new IdType("urn:uuid:1234-5678");
+ assertEquals("urn:uuid:1234-5678", id.getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.getIdPart());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testOid() {
+ IdType id = new IdType("urn:oid:1.2.3.4");
+ assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.getIdPart());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testLocal() {
+ 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("#foo", id.withResourceType("Patient").getValue());
+ assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("#foo", id.withVersion("2").getValue());
+ }
+
+ @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 testDetectLocal() {
@@ -55,16 +119,16 @@ public class IdTypeDstu2_1Test {
@Test
public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("urn:uuid:", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("cid:", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("#", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
}
@@ -75,20 +139,20 @@ public class IdTypeDstu2_1Test {
public void testComplicatedLocal() {
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal());
- assertEquals("#", id.getBaseUrl());
+ assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType());
assertNull(id.getVersionIdPart());
- assertEquals("Patient/cid:Patient-72/_history/1", id.getIdPart());
+ assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
assertEquals(id, id2);
id2 = id2.toUnqualified();
- assertFalse(id2.isLocal());
+ assertTrue(id2.isLocal());
assertNull(id2.getBaseUrl());
assertNull(id2.getResourceType());
assertNull(id2.getVersionIdPart());
- assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart());
+ assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
}
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 abdb0d5f290..3a903e512a5 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
@@ -1,6 +1,5 @@
package ca.uhn.fhir.parser;
-import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
@@ -15,79 +14,31 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
+import org.hl7.fhir.dstu2016may.model.*;
import org.hl7.fhir.dstu2016may.model.Address.AddressUse;
import org.hl7.fhir.dstu2016may.model.Address.AddressUseEnumFactory;
-import org.hl7.fhir.dstu2016may.model.Attachment;
-import org.hl7.fhir.dstu2016may.model.AuditEvent;
-import org.hl7.fhir.dstu2016may.model.Basic;
-import org.hl7.fhir.dstu2016may.model.Binary;
-import org.hl7.fhir.dstu2016may.model.Bundle;
import org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu2016may.model.Bundle.BundleType;
-import org.hl7.fhir.dstu2016may.model.Claim;
-import org.hl7.fhir.dstu2016may.model.Coding;
-import org.hl7.fhir.dstu2016may.model.Communication;
-import org.hl7.fhir.dstu2016may.model.Condition;
import org.hl7.fhir.dstu2016may.model.Condition.ConditionVerificationStatus;
-import org.hl7.fhir.dstu2016may.model.Conformance;
import org.hl7.fhir.dstu2016may.model.Conformance.UnknownContentCode;
-import org.hl7.fhir.dstu2016may.model.Coverage;
-import org.hl7.fhir.dstu2016may.model.DateTimeType;
-import org.hl7.fhir.dstu2016may.model.DateType;
-import org.hl7.fhir.dstu2016may.model.DecimalType;
-import org.hl7.fhir.dstu2016may.model.DiagnosticReport;
-import org.hl7.fhir.dstu2016may.model.EnumFactory;
import org.hl7.fhir.dstu2016may.model.Enumeration;
import org.hl7.fhir.dstu2016may.model.Enumerations.AdministrativeGender;
-import org.hl7.fhir.dstu2016may.model.ExplanationOfBenefit;
-import org.hl7.fhir.dstu2016may.model.Extension;
-import org.hl7.fhir.dstu2016may.model.HumanName;
-import org.hl7.fhir.dstu2016may.model.IdType;
import org.hl7.fhir.dstu2016may.model.Identifier.IdentifierUse;
-import org.hl7.fhir.dstu2016may.model.Linkage;
-import org.hl7.fhir.dstu2016may.model.Medication;
-import org.hl7.fhir.dstu2016may.model.MedicationOrder;
-import org.hl7.fhir.dstu2016may.model.Observation;
import org.hl7.fhir.dstu2016may.model.Observation.ObservationStatus;
-import org.hl7.fhir.dstu2016may.model.Parameters;
-import org.hl7.fhir.dstu2016may.model.Patient;
-import org.hl7.fhir.dstu2016may.model.PrimitiveType;
-import org.hl7.fhir.dstu2016may.model.Quantity;
-import org.hl7.fhir.dstu2016may.model.QuestionnaireResponse;
-import org.hl7.fhir.dstu2016may.model.Reference;
-import org.hl7.fhir.dstu2016may.model.RelatedPerson;
-import org.hl7.fhir.dstu2016may.model.SampledData;
-import org.hl7.fhir.dstu2016may.model.SimpleQuantity;
-import org.hl7.fhir.dstu2016may.model.StringType;
-import org.hl7.fhir.dstu2016may.model.UriType;
-import org.hl7.fhir.dstu2016may.model.ValueSet;
-import org.hl7.fhir.exceptions.FHIRException;
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.junit.*;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
import com.google.common.collect.Sets;
@@ -96,11 +47,8 @@ import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
import ca.uhn.fhir.parser.PatientWithExtendedContactDstu3.CustomContactComponent;
import ca.uhn.fhir.parser.XmlParserDstu2_1Test.TestPatientFor327;
-import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.TestUtil;
-import ca.uhn.fhir.validation.FhirValidator;
-import ca.uhn.fhir.validation.ValidationResult;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
@@ -1430,8 +1378,8 @@ public class JsonParserDstu2_1Test {
ourLog.info(encoded);
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getValue());
- assertEquals("urn:uuid:", parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart());
+ assertEquals(null, parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart());
assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\"")));
}
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 567b6c4fc89..c522ca07364 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
@@ -89,6 +89,21 @@ public class JsonParserDstu2Test {
assertEquals("ORG", o.getName());
}
+ @Test
+ public void testEncodeBundleOldStyleContainingResourceWithUuidBase() {
+ Patient p = new Patient();
+ p.setId(IdDt.newRandomUuid());
+ p.addName().addFamily("PATIENT");
+
+ Bundle b = new Bundle();
+ b.addEntry().setResource(p);
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder("fullUrl", p.getId().getValue(), "Patient"));
+ }
+
+
/**
* See #308
*/
@@ -1242,8 +1257,8 @@ public class JsonParserDstu2Test {
ourLog.info(encoded);
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getValue());
- assertEquals("urn:uuid:", parsed.getEntry().get(0).getResource().getId().getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getIdPart());
+ assertEquals(null, parsed.getEntry().get(0).getResource().getId().getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getIdPart());
assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\"")));
}
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 e2dea1dce3f..02535643be3 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
@@ -1,5 +1,7 @@
package org.hl7.fhir.dstu3.model;
+import static org.apache.commons.lang3.StringUtils.defaultString;
+
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
@@ -242,41 +244,12 @@ public final class IdType extends UriType implements IPrimitiveType, IId
return new IdType(getValue());
}
- private String determineLocalPrefix(String theValue) {
- if (theValue == null || theValue.isEmpty()) {
- return null;
- }
- if (theValue.startsWith("#")) {
- return "#";
- }
- int lastPrefix = -1;
- for (int i = 0; i < theValue.length(); i++) {
- char nextChar = theValue.charAt(i);
- if (nextChar == ':') {
- lastPrefix = i;
- } else if (!Character.isLetter(nextChar) || !Character.isLowerCase(nextChar)) {
- break;
- }
- }
- if (lastPrefix != -1) {
- String candidate = theValue.substring(0, lastPrefix + 1);
- if (candidate.startsWith("cid:") || candidate.startsWith("urn:")) {
- return candidate;
- } else {
- return null;
- }
- } else {
- return null;
- }
- }
-
@Override
public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdType)) {
return false;
}
- IdType id = (IdType) theArg0;
- return StringUtils.equals(getValueAsString(), id.getValueAsString());
+ return StringUtils.equals(getValueAsString(), ((IdType)theArg0).getValueAsString());
}
/**
@@ -368,8 +341,8 @@ public final class IdType extends UriType implements IPrimitiveType, IId
String retVal = super.getValue();
if (retVal == null && myHaveComponentParts) {
- if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) {
- return myBaseUrl + myUnqualifiedId;
+ if (isLocal() || isUrn()) {
+ return myUnqualifiedId;
}
StringBuilder b = new StringBuilder();
@@ -510,7 +483,11 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public boolean isLocal() {
- return "#".equals(myBaseUrl);
+ return defaultString(myUnqualifiedId).startsWith("#");
+ }
+
+ private boolean isUrn() {
+ return defaultString(myUnqualifiedId).startsWith("urn:");
}
@Override
@@ -536,8 +513,6 @@ public final class IdType extends UriType implements IPrimitiveType, IId
super.setValue(theValue);
myHaveComponentParts = false;
- String localPrefix = determineLocalPrefix(theValue);
-
if (StringUtils.isBlank(theValue)) {
myBaseUrl = null;
super.setValue(null);
@@ -546,14 +521,17 @@ public final class IdType extends UriType implements IPrimitiveType, IId
myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
super.setValue(theValue);
- myBaseUrl = "#";
- myUnqualifiedId = theValue.substring(1);
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
+ myUnqualifiedVersionId = null;
+ myResourceType = null;
+ myHaveComponentParts = true;
+ } else if (theValue.startsWith("urn:")) {
+ myBaseUrl = null;
+ myUnqualifiedId = theValue;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
- } else if (localPrefix != null) {
- myBaseUrl = localPrefix;
- myUnqualifiedId = theValue.substring(localPrefix.length());
} else {
int vidIndex = theValue.indexOf("/_history/");
int idIndex;
@@ -618,21 +596,33 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public IdType toUnqualified() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getResourceType(), getIdPart(), getVersionIdPart());
}
@Override
public IdType toUnqualifiedVersionless() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getResourceType(), getIdPart());
}
@Override
public IdType toVersionless() {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null);
}
@Override
public IdType withResourceType(String theResourceName) {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(theResourceName, getIdPart(), getVersionIdPart());
}
@@ -652,6 +642,9 @@ public final class IdType extends UriType implements IPrimitiveType, IId
*/
@Override
public IdType withServerBase(String theServerBase, String theResourceType) {
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
}
@@ -664,9 +657,14 @@ public final class IdType extends UriType implements IPrimitiveType, IId
* @return A new instance of IdType which is identical, but refers to the
* specific version of this resource ID noted by theVersion.
*/
+ @Override
public IdType withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty");
+ if (isLocal() || isUrn()) {
+ return new IdType(getValueAsString());
+ }
+
String existingValue = getValue();
int i = existingValue.indexOf("_history");
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 37162e19ad9..f21a09e6850 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
@@ -28,6 +28,69 @@ public class IdTypeDstu3Test {
TestUtil.clearAllStaticFieldsForUnitTest();
}
+ @Test
+ public void testUuid() {
+ IdType id = new IdType("urn:uuid:1234-5678");
+ assertEquals("urn:uuid:1234-5678", id.getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.getIdPart());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
+ assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testOid() {
+ IdType id = new IdType("urn:oid:1.2.3.4");
+ assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.getIdPart());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
+ assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
+ assertEquals(null, id.getVersionIdPart());
+ assertEquals(null, id.getResourceType());
+ assertEquals(null, id.getBaseUrl());
+
+ assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
+ }
+
+ @Test
+ public void testLocal() {
+ 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("#foo", id.withResourceType("Patient").getValue());
+ assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
+ assertEquals("#foo", id.withVersion("2").getValue());
+ }
+
+ @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 testDetectLocal() {
@@ -55,16 +118,16 @@ public class IdTypeDstu3Test {
@Test
public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("urn:uuid:", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("cid:", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
- assertEquals("#", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
- assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
+ assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
+ assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
}
@@ -75,20 +138,20 @@ public class IdTypeDstu3Test {
public void testComplicatedLocal() {
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal());
- assertEquals("#", id.getBaseUrl());
+ assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType());
assertNull(id.getVersionIdPart());
- assertEquals("Patient/cid:Patient-72/_history/1", id.getIdPart());
+ assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
assertEquals(id, id2);
id2 = id2.toUnqualified();
- assertFalse(id2.isLocal());
+ assertTrue(id2.isLocal());
assertNull(id2.getBaseUrl());
assertNull(id2.getResourceType());
assertNull(id2.getVersionIdPart());
- assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart());
+ assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
}
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 1b00e00eca8..79a189d58e3 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
@@ -76,6 +76,22 @@ public class XmlParserDstu3Test {
ourCtx.setNarrativeGenerator(null);
}
+ /**
+ * See #544
+ */
+ @Test
+ public void testBundleStitchReferencesByUuid() throws Exception {
+ String body = IOUtils.toString(XmlParserDstu3Test.class.getResourceAsStream("/bundle_ref_by_uuid_544.xml"), StandardCharsets.UTF_8);
+ Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, body);
+
+ DocumentManifest dm = (DocumentManifest) bundle.getEntry().get(0).getResource();
+
+ assertEquals("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3", dm.getSubject().getReference());
+
+ Patient subject = (Patient) dm.getSubject().getResource();
+ assertNotNull(subject);
+ }
+
/**
* See #414
*/
diff --git a/hapi-fhir-structures-dstu3/src/test/resources/bundle_ref_by_uuid_544.xml b/hapi-fhir-structures-dstu3/src/test/resources/bundle_ref_by_uuid_544.xml
new file mode 100644
index 00000000000..8fe8320c489
--- /dev/null
+++ b/hapi-fhir-structures-dstu3/src/test/resources/bundle_ref_by_uuid_544.xml
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file