This commit is contained in:
James Agnew 2017-01-23 18:42:46 -05:00
parent a63b42d08f
commit 599bbe236c
15 changed files with 644 additions and 264 deletions

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.model.primitive; package ca.uhn.fhir.model.primitive;
import static org.apache.commons.lang3.StringUtils.defaultString;
/* /*
* #%L * #%L
* HAPI FHIR - Core Library * 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 not use this file except in compliance with the License.
* You may obtain a copy of the License at * 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 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * 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} * regex: [a-z-Z0-9\-\.]{1,36}
* </p> * </p>
*/ */
@DatatypeDef(name = "id", profileOf=StringDt.class) @DatatypeDef(name = "id", profileOf = StringDt.class)
public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType { public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
private String myBaseUrl; private String myBaseUrl;
@ -106,9 +107,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Constructor * Constructor
* *
* @param theResourceType * @param theResourceType
* The resource type (e.g. "Patient") * The resource type (e.g. "Patient")
* @param theIdPart * @param theIdPart
* The ID (e.g. "123") * The ID (e.g. "123")
*/ */
public IdDt(String theResourceType, BigDecimal theIdPart) { public IdDt(String theResourceType, BigDecimal theIdPart) {
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart)); this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
@ -118,9 +119,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Constructor * Constructor
* *
* @param theResourceType * @param theResourceType
* The resource type (e.g. "Patient") * The resource type (e.g. "Patient")
* @param theIdPart * @param theIdPart
* The ID (e.g. "123") * The ID (e.g. "123")
*/ */
public IdDt(String theResourceType, Long theIdPart) { public IdDt(String theResourceType, Long theIdPart) {
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart)); this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
@ -130,9 +131,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Constructor * Constructor
* *
* @param theResourceType * @param theResourceType
* The resource type (e.g. "Patient") * The resource type (e.g. "Patient")
* @param theId * @param theId
* The ID (e.g. "123") * The ID (e.g. "123")
*/ */
public IdDt(String theResourceType, String theId) { public IdDt(String theResourceType, String theId) {
this(theResourceType, theId, null); this(theResourceType, theId, null);
@ -142,11 +143,11 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Constructor * Constructor
* *
* @param theResourceType * @param theResourceType
* The resource type (e.g. "Patient") * The resource type (e.g. "Patient")
* @param theId * @param theId
* The ID (e.g. "123") * The ID (e.g. "123")
* @param theVersionId * @param theVersionId
* The version ID ("e.g. "456") * The version ID ("e.g. "456")
*/ */
public IdDt(String theResourceType, String theId, String theVersionId) { public IdDt(String theResourceType, String theId, String theVersionId) {
this(null, theResourceType, theId, theVersionId); this(null, theResourceType, theId, theVersionId);
@ -156,13 +157,13 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Constructor * Constructor
* *
* @param theBaseUrl * @param theBaseUrl
* The server base URL (e.g. "http://example.com/fhir") * The server base URL (e.g. "http://example.com/fhir")
* @param theResourceType * @param theResourceType
* The resource type (e.g. "Patient") * The resource type (e.g. "Patient")
* @param theId * @param theId
* The ID (e.g. "123") * The ID (e.g. "123")
* @param theVersionId * @param theVersionId
* The version ID ("e.g. "456") * The version ID ("e.g. "456")
*/ */
public IdDt(String theBaseUrl, String theResourceType, String theId, String theVersionId) { public IdDt(String theBaseUrl, String theResourceType, String theId, String theVersionId) {
myBaseUrl = theBaseUrl; myBaseUrl = theBaseUrl;
@ -202,34 +203,6 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return getIdPartAsBigDecimal(); 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 @Override
public boolean equals(Object theArg0) { public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdDt)) { if (!(theArg0 instanceof IdDt)) {
@ -277,7 +250,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Returns the unqualified portion of this ID as a big decimal, or <code>null</code> if the value is null * Returns the unqualified portion of this ID as a big decimal, or <code>null</code> if the value is null
* *
* @throws NumberFormatException * @throws NumberFormatException
* If the value is not a valid BigDecimal * If the value is not a valid BigDecimal
*/ */
public BigDecimal getIdPartAsBigDecimal() { public BigDecimal getIdPartAsBigDecimal() {
String val = getIdPart(); String val = getIdPart();
@ -291,7 +264,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Returns the unqualified portion of this ID as a {@link Long}, or <code>null</code> if the value is null * Returns the unqualified portion of this ID as a {@link Long}, or <code>null</code> if the value is null
* *
* @throws NumberFormatException * @throws NumberFormatException
* If the value is not a valid Long * If the value is not a valid Long
*/ */
@Override @Override
public Long getIdPartAsLong() { public Long getIdPartAsLong() {
@ -316,8 +289,8 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
public String getValue() { public String getValue() {
if (super.getValue() == null && myHaveComponentParts) { if (super.getValue() == null && myHaveComponentParts) {
if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) { if (isLocal() || isUrn()) {
return myBaseUrl + myUnqualifiedId; return myUnqualifiedId;
} }
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
@ -448,11 +421,16 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
} }
/** /**
* Returns <code>true</code> if the ID is a local reference (in other words, it begins with the '#' character) * Returns <code>true</code> if the ID is a local reference (in other words,
* it begins with the '#' character)
*/ */
@Override @Override
public boolean isLocal() { public boolean isLocal() {
return "#".equals(myBaseUrl); return defaultString(myUnqualifiedId).startsWith("#");
}
private boolean isUrn() {
return defaultString(myUnqualifiedId).startsWith("urn:");
} }
@Override @Override
@ -468,6 +446,27 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
setValue(theId.getValue()); 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 * Set the value
* *
@ -485,8 +484,6 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
super.setValue(theValue); super.setValue(theValue);
myHaveComponentParts = false; myHaveComponentParts = false;
String localPrefix = determineLocalPrefix(theValue);
if (StringUtils.isBlank(theValue)) { if (StringUtils.isBlank(theValue)) {
myBaseUrl = null; myBaseUrl = null;
super.setValue(null); super.setValue(null);
@ -495,14 +492,14 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
myResourceType = null; myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) { } else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
super.setValue(theValue); super.setValue(theValue);
myBaseUrl = "#"; myBaseUrl = null;
myUnqualifiedId = theValue.substring(1); myUnqualifiedId = theValue;
myUnqualifiedVersionId = null; myUnqualifiedVersionId = null;
myResourceType = null; myResourceType = null;
myHaveComponentParts = true; myHaveComponentParts = true;
} else if (localPrefix != null) { } else if (theValue.startsWith("urn:")) {
myBaseUrl = localPrefix; myBaseUrl = null;
myUnqualifiedId = theValue.substring(localPrefix.length()); myUnqualifiedId = theValue;
myUnqualifiedVersionId = null; myUnqualifiedVersionId = null;
myResourceType = null; myResourceType = null;
myHaveComponentParts = true; myHaveComponentParts = true;
@ -567,24 +564,33 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
*/ */
@Override @Override
public IdDt toUnqualified() { public IdDt toUnqualified() {
if (isLocal() || isUrn()) {
return new IdDt(getValueAsString());
}
return new IdDt(getResourceType(), getIdPart(), getVersionIdPart()); return new IdDt(getResourceType(), getIdPart(), getVersionIdPart());
} }
@Override @Override
public IdDt toUnqualifiedVersionless() { public IdDt toUnqualifiedVersionless() {
if (isLocal()) { if (isLocal() || isUrn()) {
return toVersionless(); return new IdDt(getValueAsString());
} }
return new IdDt(getResourceType(), getIdPart()); return new IdDt(getResourceType(), getIdPart());
} }
@Override @Override
public IdDt toVersionless() { public IdDt toVersionless() {
if (isLocal() || isUrn()) {
return new IdDt(getValueAsString());
}
return new IdDt(getBaseUrl(), getResourceType(), getIdPart(), null); return new IdDt(getBaseUrl(), getResourceType(), getIdPart(), null);
} }
@Override @Override
public IdDt withResourceType(String theResourceName) { public IdDt withResourceType(String theResourceName) {
if (isLocal() || isUrn()) {
return new IdDt(getValueAsString());
}
return new IdDt(theResourceName, getIdPart(), getVersionIdPart()); return new IdDt(theResourceName, getIdPart(), getVersionIdPart());
} }
@ -593,13 +599,16 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, 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. * 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 * @param theServerBase
* The server base (e.g. "http://example.com/fhir") * The server base (e.g. "http://example.com/fhir")
* @param theResourceType * @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") * @return A fully qualified URL for this ID (e.g. "http://example.com/fhir/Patient/1")
*/ */
@Override @Override
public IdDt withServerBase(String theServerBase, String theResourceType) { public IdDt withServerBase(String theServerBase, String theResourceType) {
if (isLocal() || isUrn()) {
return new IdDt(getValueAsString());
}
return new IdDt(theServerBase, theResourceType, getIdPart(), getVersionIdPart()); return new IdDt(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
} }
@ -607,12 +616,17 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID noted by theVersion. * 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 * @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. * @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) { public IdDt withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty"); Validate.notBlank(theVersion, "Version may not be null or empty");
if (isLocal() || isUrn()) {
return new IdDt(getValueAsString());
}
String existingValue = getValue(); String existingValue = getValue();
int i = existingValue.indexOf(Constants.PARAM_HISTORY); int i = existingValue.indexOf(Constants.PARAM_HISTORY);
@ -678,25 +692,4 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return theIdPart.toString(); 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;
}
} }

View File

@ -347,7 +347,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
for (BundleEntry nextEntry : theBundle.getEntries()) { for (BundleEntry nextEntry : theBundle.getEntries()) {
theEventWriter.beginObject(); 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()); writeOptionalTagWithTextNode(theEventWriter, "fullUrl", nextEntry.getResource().getId().getValue());
} }

View File

@ -721,7 +721,6 @@ class ParserState<T> {
myInstance = theInstance; myInstance = theInstance;
} }
@SuppressWarnings("unchecked")
@Override @Override
public void wereBack() { public void wereBack() {
@ -2090,17 +2089,32 @@ class ParserState<T> {
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName()); final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
if (bundle) { if (bundle) {
FhirTerser t = myContext.newTerser();
Map<String, IBaseResource> idToResource = new HashMap<String, IBaseResource>();
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
List<IBase> 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 * Stitch together resource references
*/ */
Map<IIdType, IBaseResource> idToResource = new HashMap<IIdType, IBaseResource>();
FhirTerser t = myContext.newTerser();
List<IBaseResource> resources = t.getAllPopulatedChildElementsOfType(myInstance, IBaseResource.class); List<IBaseResource> resources = t.getAllPopulatedChildElementsOfType(myInstance, IBaseResource.class);
for (IBaseResource next : resources) { for (IBaseResource next : resources) {
IIdType id = next.getIdElement(); IIdType id = next.getIdElement();
if (id != null && id.isEmpty() == false) { if (id != null && id.isEmpty() == false) {
String resName = myContext.getResourceDefinition(next).getName(); 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<T> {
List<IBaseReference> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, IBaseReference.class); List<IBaseReference> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, IBaseReference.class);
for (IBaseReference nextRef : refs) { for (IBaseReference nextRef : refs) {
if (nextRef.isEmpty() == false && nextRef.getReferenceElement() != null) { 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) { if (target != null) {
nextRef.setResource(target); nextRef.setResource(target);
} }

View File

@ -446,7 +446,7 @@ public class XmlParser extends BaseParser implements IParser {
writeBundleResourceLink(theEventWriter, "alternate", nextEntry.getLinkAlternate()); 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()); writeOptionalTagWithValue(theEventWriter, "fullUrl", nextEntry.getResource().getId().getValue());
} }

View File

@ -130,10 +130,41 @@ public interface IIdType extends IPrimitiveType<String> {
IIdType toVersionless(); 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).
* <p>
* Note that if this object represents a local reference (e.g. <code>#foo</code>) or
* a URN (e.g. <code>urn:oid:1.2.3.4</code>) this method will simply return a copy
* of this object with no modifications.
* </p>
*/
IIdType withResourceType(String theResName); 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).
* <p>
* Note that if this object represents a local reference (e.g. <code>#foo</code>) or
* a URN (e.g. <code>urn:oid:1.2.3.4</code>) this method will simply return a copy
* of this object with no modifications.
* </p>
*/
IIdType withServerBase(String theServerBase, String theResourceName); 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).
* <p>
* Note that if this object represents a local reference (e.g. <code>#foo</code>) or
* a URN (e.g. <code>urn:oid:1.2.3.4</code>) this method will simply return a copy
* of this object with no modifications.
* </p>
*/
IIdType withVersion(String theVersion); IIdType withVersion(String theVersion);
/** /**

View File

@ -20,6 +20,71 @@ public class IdDtTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdDtTest.class); 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 @Test
public void testDetectIsIdPartValid() { public void testDetectIsIdPartValid() {
assertTrue(new IdDt("0").isIdPartValid()); assertTrue(new IdDt("0").isIdPartValid());
@ -60,16 +125,16 @@ public class IdDtTest {
@Test @Test
public void testDetectLocalBase() { public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue()); 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(null, 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("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: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(null, 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("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("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("#", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl()); assertEquals(null, new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart()); assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdDt("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
} }
@ -80,10 +145,10 @@ public class IdDtTest {
public void testComplicatedLocal() { public void testComplicatedLocal() {
IdDt id = new IdDt("#Patient/cid:Patient-72/_history/1"); IdDt id = new IdDt("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal()); assertTrue(id.isLocal());
assertEquals("#", id.getBaseUrl()); assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType()); assertNull(id.getResourceType());
assertNull(id.getVersionIdPart()); assertNull(id.getVersionIdPart());
assertEquals("Patient/cid:Patient-72/_history/1", id.getIdPart()); assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
} }

View File

@ -561,8 +561,8 @@ public class XmlParserTest {
// Re-parse the bundle // Re-parse the bundle
patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
assertEquals("#1", patient.getManagingOrganization().getReference().getValue()); assertEquals("#1", patient.getManagingOrganization().getReference().getValue());
assertEquals("#", patient.getManagingOrganization().getReference().getBaseUrl()); assertEquals(null, patient.getManagingOrganization().getReference().getBaseUrl());
assertEquals("1", patient.getManagingOrganization().getReference().getIdPart()); assertEquals("#1", patient.getManagingOrganization().getReference().getIdPart());
assertNotNull(patient.getManagingOrganization().getResource()); assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource(); org = (Organization) patient.getManagingOrganization().getResource();

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.dstu2016may.model; package org.hl7.fhir.dstu2016may.model;
import static org.apache.commons.lang3.StringUtils.defaultString;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -242,34 +244,6 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
return new IdType(getValue()); 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 @Override
public boolean equals(Object theArg0) { public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdType)) { if (!(theArg0 instanceof IdType)) {
@ -368,8 +342,8 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
String retVal = super.getValue(); String retVal = super.getValue();
if (retVal == null && myHaveComponentParts) { if (retVal == null && myHaveComponentParts) {
if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) { if (isLocal() || isUrn()) {
return myBaseUrl + myUnqualifiedId; return myUnqualifiedId;
} }
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
@ -510,7 +484,11 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public boolean isLocal() { public boolean isLocal() {
return "#".equals(myBaseUrl); return defaultString(myUnqualifiedId).startsWith("#");
}
private boolean isUrn() {
return defaultString(myUnqualifiedId).startsWith("urn:");
} }
@Override @Override
@ -536,8 +514,6 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
super.setValue(theValue); super.setValue(theValue);
myHaveComponentParts = false; myHaveComponentParts = false;
String localPrefix = determineLocalPrefix(theValue);
if (StringUtils.isBlank(theValue)) { if (StringUtils.isBlank(theValue)) {
myBaseUrl = null; myBaseUrl = null;
super.setValue(null); super.setValue(null);
@ -545,15 +521,18 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
myUnqualifiedVersionId = null; myUnqualifiedVersionId = null;
myResourceType = null; myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) { } else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
super.setValue(theValue); super.setValue(theValue);
myBaseUrl = "#"; myBaseUrl = null;
myUnqualifiedId = theValue.substring(1); myUnqualifiedId = theValue;
myUnqualifiedVersionId = null; myUnqualifiedVersionId = null;
myResourceType = null; myResourceType = null;
myHaveComponentParts = true; myHaveComponentParts = true;
} else if (localPrefix != null) { } else if (theValue.startsWith("urn:")) {
myBaseUrl = localPrefix; myBaseUrl = null;
myUnqualifiedId = theValue.substring(localPrefix.length()); myUnqualifiedId = theValue;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
} else { } else {
int vidIndex = theValue.indexOf("/_history/"); int vidIndex = theValue.indexOf("/_history/");
int idIndex; int idIndex;
@ -618,21 +597,33 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public IdType toUnqualified() { public IdType toUnqualified() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getResourceType(), getIdPart(), getVersionIdPart()); return new IdType(getResourceType(), getIdPart(), getVersionIdPart());
} }
@Override @Override
public IdType toUnqualifiedVersionless() { public IdType toUnqualifiedVersionless() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getResourceType(), getIdPart()); return new IdType(getResourceType(), getIdPart());
} }
@Override @Override
public IdType toVersionless() { public IdType toVersionless() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null); return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null);
} }
@Override @Override
public IdType withResourceType(String theResourceName) { public IdType withResourceType(String theResourceName) {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(theResourceName, getIdPart(), getVersionIdPart()); return new IdType(theResourceName, getIdPart(), getVersionIdPart());
} }
@ -652,6 +643,9 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public IdType withServerBase(String theServerBase, String theResourceType) { public IdType withServerBase(String theServerBase, String theResourceType) {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart()); return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
} }
@ -667,6 +661,10 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
public IdType withVersion(String theVersion) { public IdType withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty"); Validate.notBlank(theVersion, "Version may not be null or empty");
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
String existingValue = getValue(); String existingValue = getValue();
int i = existingValue.indexOf("_history"); int i = existingValue.indexOf("_history");

View File

@ -28,6 +28,70 @@ public class IdTypeDstu2_1Test {
TestUtil.clearAllStaticFieldsForUnitTest(); 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 @Test
public void testDetectLocal() { public void testDetectLocal() {
@ -55,16 +119,16 @@ public class IdTypeDstu2_1Test {
@Test @Test
public void testDetectLocalBase() { public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue()); 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(null, 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("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: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(null, 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("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("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("#", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl()); assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart()); 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() { public void testComplicatedLocal() {
IdType id = new IdType("#Patient/cid:Patient-72/_history/1"); IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal()); assertTrue(id.isLocal());
assertEquals("#", id.getBaseUrl()); assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType()); assertNull(id.getResourceType());
assertNull(id.getVersionIdPart()); 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"); IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
assertEquals(id, id2); assertEquals(id, id2);
id2 = id2.toUnqualified(); id2 = id2.toUnqualified();
assertFalse(id2.isLocal()); assertTrue(id2.isLocal());
assertNull(id2.getBaseUrl()); assertNull(id2.getBaseUrl());
assertNull(id2.getResourceType()); assertNull(id2.getResourceType());
assertNull(id2.getVersionIdPart()); assertNull(id2.getVersionIdPart());
assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart()); assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
} }

View File

@ -1,6 +1,5 @@
package ca.uhn.fhir.parser; package ca.uhn.fhir.parser;
import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; 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.junit.Assert.fail;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull; import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains; 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.AddressUse;
import org.hl7.fhir.dstu2016may.model.Address.AddressUseEnumFactory; 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.BundleEntryComponent;
import org.hl7.fhir.dstu2016may.model.Bundle.BundleType; 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.Condition.ConditionVerificationStatus;
import org.hl7.fhir.dstu2016may.model.Conformance;
import org.hl7.fhir.dstu2016may.model.Conformance.UnknownContentCode; 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.Enumeration;
import org.hl7.fhir.dstu2016may.model.Enumerations.AdministrativeGender; 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.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.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.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.After; import org.junit.*;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import com.google.common.collect.Sets; 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.IParserErrorHandler.IParseLocation;
import ca.uhn.fhir.parser.PatientWithExtendedContactDstu3.CustomContactComponent; import ca.uhn.fhir.parser.PatientWithExtendedContactDstu3.CustomContactComponent;
import ca.uhn.fhir.parser.XmlParserDstu2_1Test.TestPatientFor327; 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.rest.server.Constants;
import ca.uhn.fhir.util.TestUtil; 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.JSON;
import net.sf.json.JSONSerializer; import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig; import net.sf.json.JsonConfig;
@ -1430,8 +1378,8 @@ public class JsonParserDstu2_1Test {
ourLog.info(encoded); ourLog.info(encoded);
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getValue()); 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(null, parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart()); 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\""))); assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\"")));
} }

View File

@ -89,6 +89,21 @@ public class JsonParserDstu2Test {
assertEquals("ORG", o.getName()); 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 * See #308
*/ */
@ -1242,8 +1257,8 @@ public class JsonParserDstu2Test {
ourLog.info(encoded); ourLog.info(encoded);
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getValue()); 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(null, parsed.getEntry().get(0).getResource().getId().getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getId().getIdPart()); 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\""))); assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\"")));
} }

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.dstu3.model; package org.hl7.fhir.dstu3.model;
import static org.apache.commons.lang3.StringUtils.defaultString;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -242,41 +244,12 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
return new IdType(getValue()); 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 @Override
public boolean equals(Object theArg0) { public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdType)) { if (!(theArg0 instanceof IdType)) {
return false; return false;
} }
IdType id = (IdType) theArg0; return StringUtils.equals(getValueAsString(), ((IdType)theArg0).getValueAsString());
return StringUtils.equals(getValueAsString(), id.getValueAsString());
} }
/** /**
@ -368,8 +341,8 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
String retVal = super.getValue(); String retVal = super.getValue();
if (retVal == null && myHaveComponentParts) { if (retVal == null && myHaveComponentParts) {
if (determineLocalPrefix(myBaseUrl) != null && myResourceType == null && myUnqualifiedVersionId == null) { if (isLocal() || isUrn()) {
return myBaseUrl + myUnqualifiedId; return myUnqualifiedId;
} }
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
@ -510,7 +483,11 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public boolean isLocal() { public boolean isLocal() {
return "#".equals(myBaseUrl); return defaultString(myUnqualifiedId).startsWith("#");
}
private boolean isUrn() {
return defaultString(myUnqualifiedId).startsWith("urn:");
} }
@Override @Override
@ -536,8 +513,6 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
super.setValue(theValue); super.setValue(theValue);
myHaveComponentParts = false; myHaveComponentParts = false;
String localPrefix = determineLocalPrefix(theValue);
if (StringUtils.isBlank(theValue)) { if (StringUtils.isBlank(theValue)) {
myBaseUrl = null; myBaseUrl = null;
super.setValue(null); super.setValue(null);
@ -546,14 +521,17 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
myResourceType = null; myResourceType = null;
} else if (theValue.charAt(0) == '#' && theValue.length() > 1) { } else if (theValue.charAt(0) == '#' && theValue.length() > 1) {
super.setValue(theValue); super.setValue(theValue);
myBaseUrl = "#"; myBaseUrl = null;
myUnqualifiedId = theValue.substring(1); myUnqualifiedId = theValue;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
} else if (theValue.startsWith("urn:")) {
myBaseUrl = null;
myUnqualifiedId = theValue;
myUnqualifiedVersionId = null; myUnqualifiedVersionId = null;
myResourceType = null; myResourceType = null;
myHaveComponentParts = true; myHaveComponentParts = true;
} else if (localPrefix != null) {
myBaseUrl = localPrefix;
myUnqualifiedId = theValue.substring(localPrefix.length());
} else { } else {
int vidIndex = theValue.indexOf("/_history/"); int vidIndex = theValue.indexOf("/_history/");
int idIndex; int idIndex;
@ -618,21 +596,33 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public IdType toUnqualified() { public IdType toUnqualified() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getResourceType(), getIdPart(), getVersionIdPart()); return new IdType(getResourceType(), getIdPart(), getVersionIdPart());
} }
@Override @Override
public IdType toUnqualifiedVersionless() { public IdType toUnqualifiedVersionless() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getResourceType(), getIdPart()); return new IdType(getResourceType(), getIdPart());
} }
@Override @Override
public IdType toVersionless() { public IdType toVersionless() {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null); return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null);
} }
@Override @Override
public IdType withResourceType(String theResourceName) { public IdType withResourceType(String theResourceName) {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(theResourceName, getIdPart(), getVersionIdPart()); return new IdType(theResourceName, getIdPart(), getVersionIdPart());
} }
@ -652,6 +642,9 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
*/ */
@Override @Override
public IdType withServerBase(String theServerBase, String theResourceType) { public IdType withServerBase(String theServerBase, String theResourceType) {
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart()); return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
} }
@ -664,9 +657,14 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
* @return A new instance of IdType which is identical, but refers to the * @return A new instance of IdType which is identical, but refers to the
* specific version of this resource ID noted by theVersion. * specific version of this resource ID noted by theVersion.
*/ */
@Override
public IdType withVersion(String theVersion) { public IdType withVersion(String theVersion) {
Validate.notBlank(theVersion, "Version may not be null or empty"); Validate.notBlank(theVersion, "Version may not be null or empty");
if (isLocal() || isUrn()) {
return new IdType(getValueAsString());
}
String existingValue = getValue(); String existingValue = getValue();
int i = existingValue.indexOf("_history"); int i = existingValue.indexOf("_history");

View File

@ -28,6 +28,69 @@ public class IdTypeDstu3Test {
TestUtil.clearAllStaticFieldsForUnitTest(); 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 @Test
public void testDetectLocal() { public void testDetectLocal() {
@ -55,16 +118,16 @@ public class IdTypeDstu3Test {
@Test @Test
public void testDetectLocalBase() { public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue()); 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(null, 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("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: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(null, 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("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("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("#", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl()); assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart()); assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
} }
@ -75,20 +138,20 @@ public class IdTypeDstu3Test {
public void testComplicatedLocal() { public void testComplicatedLocal() {
IdType id = new IdType("#Patient/cid:Patient-72/_history/1"); IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal()); assertTrue(id.isLocal());
assertEquals("#", id.getBaseUrl()); assertEquals(null, id.getBaseUrl());
assertNull(id.getResourceType()); assertNull(id.getResourceType());
assertNull(id.getVersionIdPart()); 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"); IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
assertEquals(id, id2); assertEquals(id, id2);
id2 = id2.toUnqualified(); id2 = id2.toUnqualified();
assertFalse(id2.isLocal()); assertTrue(id2.isLocal());
assertNull(id2.getBaseUrl()); assertNull(id2.getBaseUrl());
assertNull(id2.getResourceType()); assertNull(id2.getResourceType());
assertNull(id2.getVersionIdPart()); assertNull(id2.getVersionIdPart());
assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart()); assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
} }

View File

@ -76,6 +76,22 @@ public class XmlParserDstu3Test {
ourCtx.setNarrativeGenerator(null); 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 * See #414
*/ */

File diff suppressed because one or more lines are too long