Skip to content

Commit

Permalink
Work on #544
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesagnew committed Jan 23, 2017
1 parent a63b42d commit 599bbe2
Show file tree
Hide file tree
Showing 15 changed files with 644 additions and 264 deletions.
165 changes: 79 additions & 86 deletions 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
Expand All @@ -10,7 +11,7 @@
* 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,
Expand Down Expand Up @@ -52,7 +53,7 @@
* regex: [a-z-Z0-9\-\.]{1,36}
* </p>
*/
@DatatypeDef(name = "id", profileOf=StringDt.class)
@DatatypeDef(name = "id", profileOf = StringDt.class)
public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {

private String myBaseUrl;
Expand Down Expand Up @@ -106,9 +107,9 @@ public IdDt(@SimpleSetter.Parameter(name = "theId") String theValue) {
* 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));
Expand All @@ -118,9 +119,9 @@ public IdDt(String theResourceType, BigDecimal theIdPart) {
* 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));
Expand All @@ -130,9 +131,9 @@ public IdDt(String theResourceType, Long theIdPart) {
* 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);
Expand All @@ -142,11 +143,11 @@ public IdDt(String theResourceType, String theId) {
* 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);
Expand All @@ -156,13 +157,13 @@ public IdDt(String theResourceType, String theId, String theVersionId) {
* 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;
Expand Down Expand Up @@ -202,34 +203,6 @@ public BigDecimal asBigDecimal() {
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)) {
Expand Down Expand Up @@ -277,7 +250,7 @@ public String getIdPart() {
* Returns the unqualified portion of this ID as a big decimal, or <code>null</code> 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();
Expand All @@ -291,7 +264,7 @@ public BigDecimal getIdPartAsBigDecimal() {
* Returns the unqualified portion of this ID as a {@link Long}, or <code>null</code> 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() {
Expand All @@ -315,11 +288,11 @@ public String getResourceType() {
@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);
Expand Down Expand Up @@ -448,18 +421,23 @@ public boolean isIdPartValidLong() {
}

/**
* 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
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 <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
*/
Expand All @@ -468,6 +446,27 @@ public void setId(IdDt theId) {
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
*
Expand All @@ -484,9 +483,7 @@ public IdDt setValue(String theValue) throws DataFormatException {
// TODO: add validation
super.setValue(theValue);
myHaveComponentParts = false;

String localPrefix = determineLocalPrefix(theValue);


if (StringUtils.isBlank(theValue)) {
myBaseUrl = null;
super.setValue(null);
Expand All @@ -495,14 +492,14 @@ public IdDt setValue(String theValue) throws DataFormatException {
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;
Expand Down Expand Up @@ -567,24 +564,33 @@ public String toString() {
*/
@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());
}

Expand All @@ -593,26 +599,34 @@ public IdDt withResourceType(String theResourceName) {
* 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());
}

/**
* 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);
Expand Down Expand Up @@ -678,25 +692,4 @@ private static String toPlainStringWithNpeThrowIfNeeded(Long theIdPart) {
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;
}

}
Expand Up @@ -347,7 +347,7 @@ private void encodeBundleToWriterInDstu2Format(Bundle theBundle, JsonLikeWriter
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());
}

Expand Down

0 comments on commit 599bbe2

Please sign in to comment.