Start preparingh for multiple versions of FHIR

This commit is contained in:
James Agnew 2014-07-17 09:53:52 -04:00
parent 41f160ed67
commit bb14ad09ea
22 changed files with 690 additions and 331 deletions

View File

@ -10,6 +10,10 @@
<action type="add">
Allow server methods to return wildcard genrric types (e.g. List&lt;? extends IResource&gt;)
</action>
<action type="add">
Search parameters are not properly escaped and unescaped. E.g. for a token parameter such as
"&amp;identifier=system|codepart1\|codepart2"
</action>
</release>
<release version="0.4" date="2014-Jul-13">
<action type="add">

View File

@ -41,7 +41,6 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import ca.uhn.fhir.model.api.BaseResourceReference;
import ca.uhn.fhir.model.api.CodeableConceptElement;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.ICodeEnum;
@ -62,6 +61,7 @@ import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.Extension;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
@ -457,7 +457,7 @@ class ModelScanner {
if (IElement.class.isAssignableFrom(nextElementType)) {
addScanAlso((Class<? extends IElement>) nextElementType);
}
} else if (BaseResourceReference.class.isAssignableFrom(nextElementType)) {
} else if (BaseResourceReferenceDt.class.isAssignableFrom(nextElementType)) {
/*
* Child is a resource reference
*/

View File

@ -28,11 +28,11 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import ca.uhn.fhir.model.api.BaseResourceReference;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefinition {
@ -51,7 +51,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override
public String getChildNameByDatatype(Class<? extends IElement> theDatatype) {
if (BaseResourceReference.class.isAssignableFrom(theDatatype)) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) {
return getElementName();
}
return null;
@ -59,7 +59,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IElement> theDatatype) {
if (BaseResourceReference.class.isAssignableFrom(theDatatype)) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) {
return myRuntimeDef;
}
return null;

View File

@ -30,11 +30,11 @@ import java.util.Set;
import org.apache.commons.lang3.text.WordUtils;
import ca.uhn.fhir.model.api.BaseResourceReference;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildDefinition {
@ -104,7 +104,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition("valueResource", types);
def.sealAndInitialize(theClassToElementDefinitions);
myAttributeNameToDefinition.put("valueResource", def);
myDatatypeToDefinition.put(BaseResourceReference.class, def);
myDatatypeToDefinition.put(BaseResourceReferenceDt.class, def);
myDatatypeToDefinition.put(ResourceReferenceDt.class, def);
}

View File

@ -24,17 +24,17 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ca.uhn.fhir.model.api.BaseResourceReference;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementDefinition<BaseResourceReference> {
public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementDefinition<BaseResourceReferenceDt> {
private final List<Class<? extends IResource>> myResourceTypes;
private HashMap<Class<? extends IResource>, RuntimeResourceDefinition> myResourceTypeToDefinition;
public RuntimeResourceReferenceDefinition(String theName, List<Class<? extends IResource>> theResourceTypes) {
super(theName, BaseResourceReference.class);
super(theName, BaseResourceReferenceDt.class);
if (theResourceTypes == null || theResourceTypes.isEmpty()) {
throw new ConfigurationException("Element '" + theName + "' has no resource types noted");
}

View File

@ -24,6 +24,8 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
@ -62,6 +64,13 @@ public abstract class BaseResource extends BaseElement implements IResource {
return myId;
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
b.append("id", getId().toUnqualified());
return b.toString();
}
public CodeDt getLanguage() {
return myLanguage;
}

View File

@ -0,0 +1,93 @@
package ca.uhn.fhir.model.base.composite;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.param.ParameterUtil;
public abstract class BaseCodingDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
/**
* Gets the value(s) for <b>code</b> (Symbol in syntax defined by the system). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post-coordination)
* </p>
*/
public abstract CodeDt getCode();
@Override
public String getQueryParameterQualifier() {
return null;
}
/**
* Gets the value(s) for <b>system</b> (Identity of the terminology system). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> The identification of the code system that defines the meaning of the symbol in the code.
* </p>
*/
public abstract UriDt getSystem();
/**
* {@inheritDoc}
*/
@Override
public String getValueAsQueryToken() {
if (getSystem().getValueAsString() != null) {
return ParameterUtil.escape(StringUtils.defaultString(getSystem().getValueAsString())) + '|' + ParameterUtil.escape(getCode().getValueAsString());
} else {
return ParameterUtil.escape(getCode().getValueAsString());
}
}
/**
* {@inheritDoc}
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
if (barIndex != -1) {
setSystem(theParameter.substring(0, barIndex));
setCode(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
} else {
setCode(ParameterUtil.unescape(theParameter));
}
}
/**
* Returns true if <code>this</code> Coding has the same {@link CodingDt#getCode() Code} and {@link CodingDt#getSystem() system} (as compared by simple equals comparison). Does not compare other
* Codes (e.g. {@link CodingDt#getUse() use}) or any extensions.
*/
public boolean matchesSystemAndCode(BaseCodingDt theCoding) {
if (theCoding == null) {
return false;
}
return getCode().equals(theCoding.getCode()) && getSystem().equals(theCoding.getSystem());
}
/**
* Sets the value for <b>code</b> (Symbol in syntax defined by the system)
*
* <p>
* <b>Definition:</b> A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post-coordination)
* </p>
*/
public abstract BaseCodingDt setCode(String theCode);
/**
* Sets the value for <b>system</b> (Identity of the terminology system)
*
* <p>
* <b>Definition:</b> The identification of the code system that defines the meaning of the symbol in the code.
* </p>
*/
public abstract BaseCodingDt setSystem(String theUri);
}

View File

@ -0,0 +1,80 @@
package ca.uhn.fhir.model.base.composite;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.primitive.StringDt;
public abstract class BaseHumanNameDt extends BaseIdentifiableElement {
/**
* Gets the value(s) for <b>family</b> (Family name (often called 'Surname')). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> The part of a name that links to the genealogy. In some cultures (e.g. Eritrea) the family name of a son is the first name of his father.
* </p>
*/
public abstract java.util.List<StringDt> getFamily();
/**
* Returns all repetitions of {@link $ hash}getFamily() family name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getFamilyAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getFamily());
}
/**
* Gets the value(s) for <b>given</b> (Given names (not always 'first'). Includes middle names). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> Given name
* </p>
*/
public abstract java.util.List<StringDt> getGiven();
/**
* Returns all repetitions of {@link $ hash}getGiven() given name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getGivenAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getGiven());
}
/**
* Gets the value(s) for <b>prefix</b> (Parts that come before the name). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the start of the name
* </p>
*/
public abstract java.util.List<StringDt> getPrefix();
/**
* Returns all repetitions of {@link $ hash}getPrefix() prefix name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getPrefixAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getPrefix());
}
/**
* Gets the value(s) for <b>suffix</b> (Parts that come after the name). creating it if it does not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b> Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name
* </p>
*/
public abstract java.util.List<StringDt> getSuffix();
/**
* Returns all repetitions of {@link $ hash}Suffix() suffix} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getSuffixAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getSuffix());
}
}

View File

@ -0,0 +1,105 @@
package ca.uhn.fhir.model.base.composite;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.param.ParameterUtil;
public abstract class BaseIdentifierDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
@Override
public String getQueryParameterQualifier() {
return null;
}
/**
* Gets the value(s) for <b>system</b> (The namespace for the identifier).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* Establishes the namespace in which set of possible id values is unique.
* </p>
*/
public abstract UriDt getSystem() ;
/**
* Gets the value(s) for <b>value</b> (The value that is unique).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* The portion of the identifier typically displayed to the user and which is unique within the context of the system.
* </p>
*/
public abstract StringDt getValue();
/**
* {@inheritDoc}
*/
@Override
public String getValueAsQueryToken() {
if (getSystem().getValueAsString() != null) {
return ParameterUtil.escape(StringUtils.defaultString(getSystem().getValueAsString())) + '|' + ParameterUtil.escape(getValue().getValueAsString());
} else {
return ParameterUtil.escape(getValue().getValueAsString());
}
}
/**
* Returns true if <code>this</code> identifier has the same {@link IdentifierDt#[[#]]#getValue() value}
* and {@link IdentifierDt#[[#]]#getSystem() system} (as compared by simple equals comparison).
* Does not compare other values (e.g. {@link IdentifierDt#[[#]]#getUse() use}) or any extensions.
*/
public boolean matchesSystemAndValue(BaseIdentifierDt theIdentifier) {
if (theIdentifier == null) {
return false;
}
return getValue().equals(theIdentifier.getValue()) && getSystem().equals(theIdentifier.getSystem());
}
/**
* Sets the value for <b>system</b> (The namespace for the identifier)
*
* <p>
* <b>Definition:</b>
* Establishes the namespace in which set of possible id values is unique.
* </p>
*/
public abstract BaseIdentifierDt setSystem( String theUri);
/**
* Sets the value for <b>value</b> (The value that is unique)
*
* <p>
* <b>Definition:</b>
* The portion of the identifier typically displayed to the user and which is unique within the context of the system.
* </p>
*/
public abstract BaseIdentifierDt setValue( String theString);
/**
* {@inheritDoc}
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter,'|');
if (barIndex != -1) {
setSystem(theParameter.substring(0, barIndex));
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
} else {
setValue(ParameterUtil.unescape(theParameter));
}
}
}

View File

@ -0,0 +1,190 @@
package ca.uhn.fhir.model.base.composite;
import java.math.BigDecimal;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
public abstract class BaseQuantityDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
/**
* Sets the value(s) for <b>value</b> (Numerical value (with implicit precision))
*
* <p>
* <b>Definition:</b>
* The value of the measured amount. The value includes an implicit precision in the presentation of the value
* </p>
*/
public abstract BaseQuantityDt setValue(BigDecimal theValue);
@Override
public void setValueAsQueryToken(String theQualifier, String theValue) {
getComparator().setValue(null);
setCode( null);
setSystem(null);
setUnits( null);
setValue( null);
if (theValue == null) {
return;
}
String[] parts = theValue.split("\\|");
if (parts.length > 0 && StringUtils.isNotBlank(parts[0])) {
if (parts[0].startsWith("<=")) {
getComparator().setValue(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS.getCode());
setValue(new BigDecimal(parts[0].substring(2)));
} else if (parts[0].startsWith("<")) {
getComparator().setValue(QuantityCompararatorEnum.LESSTHAN.getCode());
setValue(new BigDecimal(parts[0].substring(1)));
} else if (parts[0].startsWith(">=")) {
getComparator().setValue(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS.getCode());
setValue(new BigDecimal(parts[0].substring(2)));
} else if (parts[0].startsWith(">")) {
getComparator().setValue(QuantityCompararatorEnum.GREATERTHAN.getCode());
setValue(new BigDecimal(parts[0].substring(1)));
} else {
setValue(new BigDecimal(parts[0]));
}
}
if (parts.length > 1 && StringUtils.isNotBlank(parts[1])) {
setSystem(parts[1]);
}
if (parts.length > 2 && StringUtils.isNotBlank(parts[2])) {
setUnits(parts[2]);
}
}
/**
* Gets the value(s) for <b>comparator</b> (< | <= | >= | > - how to understand the value).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues. E.g. if the comparator is \"<\" , then the real value is < stated value
* </p>
*/
public abstract BoundCodeDt<?> getComparator();
@Override
public String getValueAsQueryToken() {
StringBuilder b= new StringBuilder();
if (getComparator() != null) {
b.append(getComparator().getValue());
}
if (!getValue().isEmpty()) {
b.append(getValue().getValueAsString());
}
b.append('|');
if (!getSystem().isEmpty()) {
b.append(getSystem().getValueAsString());
}
b.append('|');
if (!getUnits().isEmpty()) {
b.append(getUnits().getValueAsString());
}
return b.toString();
}
@Override
public String getQueryParameterQualifier() {
return null;
}
/**
* Sets the value for <b>units</b> (Unit representation)
*
* <p>
* <b>Definition:</b>
* A human-readable form of the units
* </p>
*/
public abstract BaseQuantityDt setUnits( String theString);
/**
* Gets the value(s) for <b>system</b> (System that defines coded unit form).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* The identification of the system that provides the coded form of the unit
* </p>
*/
public abstract UriDt getSystem();
/**
* Sets the value for <b>system</b> (System that defines coded unit form)
*
* <p>
* <b>Definition:</b>
* The identification of the system that provides the coded form of the unit
* </p>
*/
public abstract BaseQuantityDt setSystem( String theUri);
/**
* Gets the value(s) for <b>code</b> (Coded form of the unit).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* A computer processable form of the units in some unit representation system
* </p>
*/
public abstract CodeDt getCode();
/**
* Sets the value for <b>code</b> (Coded form of the unit)
*
* <p>
* <b>Definition:</b>
* A computer processable form of the units in some unit representation system
* </p>
*/
public abstract BaseQuantityDt setCode( String theCode);
/**
* Gets the value(s) for <b>units</b> (Unit representation).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* A human-readable form of the units
* </p>
*/
public abstract StringDt getUnits() ;
/**
* Gets the value(s) for <b>value</b> (Numerical value (with implicit precision)).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* The value of the measured amount. The value includes an implicit precision in the presentation of the value
* </p>
*/
public abstract DecimalDt getValue();
}

View File

@ -1,4 +1,4 @@
package ca.uhn.fhir.model.api;
package ca.uhn.fhir.model.base.composite;
/*
* #%L
@ -29,43 +29,43 @@ import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.client.BaseClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
public abstract class BaseResourceReference extends BaseIdentifiableElement {
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReference.class);
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
private IResource myResource;
/**
* Constructor
*
* @param theResource
*/
public BaseResourceReference() {
public BaseResourceReferenceDt() {
// nothing
}
/**
* Constructor
*
* @param theResource The loaded resource itself
* @param theResource
* The loaded resource itself
*/
public BaseResourceReference(IResource theResource) {
public BaseResourceReferenceDt(IResource theResource) {
myResource = theResource;
setReference(theResource.getId());
}
public abstract BaseResourceReference setReference(IdDt theReference);
protected abstract IdDt getReference();
/**
* Gets the actual loaded and parsed resource instance, <b>if it is already present</b>. This
* method will return the resource instance only if it has previously been loaded using
* {@link #loadResource(IRestfulClient)} or it was contained within the resource containing
* this resource.
* Gets the actual loaded and parsed resource instance, <b>if it is already present</b>. This method will return the resource instance only if it has previously been loaded using
* {@link #loadResource(IRestfulClient)} or it was contained within the resource containing this resource.
*
* @see See {@link #loadResource(IRestfulClient)}
* @see See the FHIR specification section on <a href="http://www.hl7.org/implement/standards/fhir/references.html#id>contained resources</a>
@ -74,7 +74,6 @@ public abstract class BaseResourceReference extends BaseIdentifiableElement {
return myResource;
}
@Override
protected boolean isBaseEmpty() {
return super.isBaseEmpty() && myResource == null;
@ -123,10 +122,18 @@ public abstract class BaseResourceReference extends BaseIdentifiableElement {
return myResource;
}
protected abstract IdDt getReference();
public abstract BaseResourceReferenceDt setReference(IdDt theReference);
public void setResource(IResource theResource) {
myResource = theResource;
}
@Override
public String toString() {
org.apache.commons.lang3.builder.ToStringBuilder b = new org.apache.commons.lang3.builder.ToStringBuilder(this, org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE);
b.append("reference", getReference().getValueAsString());
b.append("loaded", getResource() != null);
return b.toString();
}
}

View File

@ -45,6 +45,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.primitive.BooleanDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -66,7 +67,7 @@ import ca.uhn.fhir.model.primitive.UriDt;
*/
@DatatypeDef(name="CodingDt")
public class CodingDt
extends BaseIdentifiableElement implements ICompositeDatatype , IQueryParameterType {
extends BaseCodingDt implements ICompositeDatatype , IQueryParameterType {
/**
* Constructor
@ -389,43 +390,6 @@ public class CodingDt
/**
* Returns true if <code>this</code> Coding has the same {@link CodingDt#getCode() Code}
* and {@link CodingDt#getSystem() system} (as compared by simple equals comparison).
* Does not compare other Codes (e.g. {@link CodingDt#getUse() use}) or any extensions.
*/
public boolean matchesSystemAndCode(CodingDt theCoding) {
if (theCoding == null) {
return false;
}
return getCode().equals(theCoding.getCode()) && getSystem().equals(theCoding.getSystem());
}
/**
* {@inheritDoc}
*/
@Override
public String getValueAsQueryToken() {
if (org.apache.commons.lang3.StringUtils.isNotBlank(getSystem().getValueAsString())) {
return getSystem().getValueAsString() + '|' + getCode().getValueAsString();
} else {
return getCode().getValueAsString();
}
}
/**
* {@inheritDoc}
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = theParameter.indexOf('|');
if (barIndex != -1) {
setSystem(new UriDt(theParameter.substring(0, barIndex)));
setCode(theParameter.substring(barIndex + 1));
} else {
setCode(theParameter);
}
}
@Override
public String getQueryParameterQualifier() {

View File

@ -38,12 +38,12 @@ package ca.uhn.fhir.model.dstu.composite;
import java.util.List;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.base.composite.BaseHumanNameDt;
import ca.uhn.fhir.model.dstu.valueset.NameUseEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
@ -66,7 +66,7 @@ import ca.uhn.fhir.util.DatatypeUtil;
*/
@DatatypeDef(name="HumanNameDt")
public class HumanNameDt
extends BaseIdentifiableElement implements ICompositeDatatype {
extends BaseHumanNameDt implements ICompositeDatatype {
/**
* Constructor

View File

@ -38,6 +38,8 @@ package ca.uhn.fhir.model.dstu.composite;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IElement;
@ -51,6 +53,7 @@ import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.param.ParameterUtil;
/**
* HAPI/FHIR <b>IdentifierDt</b> Datatype
@ -412,10 +415,10 @@ public class IdentifierDt
*/
@Override
public String getValueAsQueryToken() {
if (org.apache.commons.lang3.StringUtils.isNotBlank(getSystem().getValueAsString())) {
return getSystem().getValueAsString() + '|' + getValue().getValueAsString();
if (getSystem().getValueAsString() != null) {
return ParameterUtil.escape(StringUtils.defaultString(getSystem().getValueAsString())) + '|' + ParameterUtil.escape(getValue().getValueAsString());
} else {
return getValue().getValueAsString();
return ParameterUtil.escape(getValue().getValueAsString());
}
}
@ -424,12 +427,12 @@ public class IdentifierDt
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = theParameter.indexOf('|');
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter,'|');
if (barIndex != -1) {
setSystem(new UriDt(theParameter.substring(0, barIndex)));
setValue(theParameter.substring(barIndex + 1));
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
} else {
setValue(theParameter);
setValue(ParameterUtil.unescape(theParameter));
}
}

View File

@ -41,7 +41,6 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IQueryParameterType;
@ -49,6 +48,7 @@ import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
@ -72,7 +72,7 @@ import ca.uhn.fhir.model.primitive.UriDt;
*/
@DatatypeDef(name="QuantityDt")
public class QuantityDt
extends BaseIdentifiableElement implements ICompositeDatatype , IQueryParameterType {
extends BaseQuantityDt implements ICompositeDatatype , IQueryParameterType {
/**
* Constructor

View File

@ -38,13 +38,13 @@ package ca.uhn.fhir.model.dstu.composite;
import java.util.List;
import ca.uhn.fhir.model.api.BaseResourceReference;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -64,7 +64,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
*/
@DatatypeDef(name="ResourceReferenceDt")
public class ResourceReferenceDt
extends BaseResourceReference implements ICompositeDatatype {
extends BaseResourceReferenceDt implements ICompositeDatatype {
/**
* Constructor

View File

@ -137,8 +137,6 @@ public class IdDt extends BasePrimitive<String> {
* The version ID ("e.g. "456")
*/
public IdDt(String theResourceType, String theId, String theVersionId) {
Validate.notBlank(theId, "ID must not be blank");
myResourceType = theResourceType;
myUnqualifiedId = theId;
myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionId, null);

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.param;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@ -51,6 +51,7 @@ import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.TagListParam;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.IncludeParam;
@ -96,6 +97,17 @@ public class ParameterUtil {
return findParamAnnotationIndex(theMethod, TagListParam.class);
}
public static int nonEscapedIndexOf(String theString, char theCharacter) {
for (int i =0; i < theString.length(); i++) {
if (theString.charAt(i)==theCharacter) {
if (i == 0 || theString.charAt(i-1) != '\\') {
return i;
}
}
}
return -1;
}
public static Integer findVersionIdParameterIndex(Method theMethod) {
return findParamAnnotationIndex(theMethod, VersionIdParam.class);
}
@ -322,4 +334,67 @@ public class ParameterUtil {
};
}
/**
* Escapes a string according to the rules for parameter escaping specified
* in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
*/
public static String escape(String theValue) {
if (theValue == null) {
return theValue;
}
StringBuilder b = new StringBuilder();
for (int i = 0; i < theValue.length();i++) {
char next = theValue.charAt(i);
switch (next) {
case '$':
case ',':
case '|':
b.append('\\');
// fall through
default:
b.append(next);
}
}
return b.toString();
}
/**
* Unescapes a string according to the rules for parameter escaping specified
* in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
*/
public static String unescape(String theValue) {
if (theValue == null) {
return theValue;
}
if (theValue.indexOf('\\')==-1) {
return theValue;
}
StringBuilder b = new StringBuilder();
for (int i = 0; i < theValue.length();i++) {
char next = theValue.charAt(i);
if (next == '\\') {
if (i == theValue.length()-1) {
b.append(next);
} else {
switch (theValue.charAt(i+1)) {
case '$':
case ',':
case '|':
continue;
default:
b.append(next);
}
}
} else {
b.append(next);
}
}
return b.toString();
}
}

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.model.primitive;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
@ -8,28 +8,6 @@ import ca.uhn.fhir.model.dstu.composite.CodingDt;
public class CodingDtTest {
@Test
public void testTokenWithPipeInValue() {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(null, "a|b|c");
assertEquals("a", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getCode().getValue());
assertEquals("a|b|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValueAndNoSystem() {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(null, "|b|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getCode().getValue());
// TODO: this should be escaped or something?
assertEquals("b|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenNoSystem() {
CodingDt dt = new CodingDt();
@ -40,4 +18,38 @@ public class CodingDtTest {
assertEquals("c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValue() {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(null, "a|b|c");
assertEquals("a", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getCode().getValue());
assertEquals("a|b\\|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValueAndNoSystem() {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(null, "|b\\|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getCode().getValue());
assertEquals("|b\\|c", dt.getValueAsQueryToken());
}
/**
* Technically the second pipe should have been escaped.. But we should be nice about it
*/
@Test
public void testTokenWithPipeInValueAndNoSystemAndBeLenient() {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(null, "|b|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getCode().getValue());
assertEquals("|b\\|c", dt.getValueAsQueryToken());
}
}

View File

@ -8,28 +8,6 @@ import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
public class IdentifierDtTest {
@Test
public void testTokenWithPipeInValue() {
IdentifierDt dt = new IdentifierDt();
dt.setValueAsQueryToken(null, "a|b|c");
assertEquals("a", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getValue().getValue());
assertEquals("a|b|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValueAndNoSystem() {
IdentifierDt dt = new IdentifierDt();
dt.setValueAsQueryToken(null, "|b|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getValue().getValue());
// TODO: this should probably be an error or escaped or something, since it will be interpreted as system=b, code=c
assertEquals("b|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenNoSystem() {
IdentifierDt dt = new IdentifierDt();
@ -40,4 +18,40 @@ public class IdentifierDtTest {
assertEquals("c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValue() {
IdentifierDt dt = new IdentifierDt();
dt.setValueAsQueryToken(null, "a|b|c");
assertEquals("a", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getValue().getValue());
assertEquals("a|b\\|c", dt.getValueAsQueryToken());
}
@Test
public void testTokenWithPipeInValueAndNoSystem() {
IdentifierDt dt = new IdentifierDt();
dt.setValueAsQueryToken(null, "|b\\|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getValue().getValue());
assertEquals("|b\\|c", dt.getValueAsQueryToken());
}
/**
* Technically the second pipe should have been escaped.. But we should be nice about it
*/
@Test
public void testTokenWithPipeInValueAndNoSystemAndBeLenient() {
IdentifierDt dt = new IdentifierDt();
dt.setValueAsQueryToken(null, "|b|c");
assertEquals("", dt.getSystem().getValueAsString());
assertEquals("b|c", dt.getValue().getValue());
assertEquals("|b\\|c", dt.getValueAsQueryToken());
}
}

View File

@ -13,8 +13,9 @@
<property name="servers">
<list>
<value>home , UHN/HAPI Server , http://fhirtest.uhn.ca/base</value>
<value>hi , Health Intersections , http://fhir.healthintersections.com.au/open</value>
<value>furore , Spark - Furore Reference Server , http://spark.furore.com/fhir</value>
<value>hi , Health Intersections (Ref Server) , http://fhir.healthintersections.com.au/open</value>
<value>hidev , Health Intersections (Developnent FHIR) , http://fhir-dev.healthintersections.com.au/open</value>
<value>furore , Spark - Furore (Ref Server) , http://spark.furore.com/fhir</value>
<value>blaze , Blaze (Orion Health) , https://fhir.orionhealth.com/blaze/fhir</value>
<value>oridashi , Oridashi , http://demo.oridashi.com.au:8190</value>
<!-- <value>fhirbase , FHIRPlace (Health Samurai) , http://try-fhirplace.hospital-systems.com/ </value> -->

View File

@ -8,6 +8,7 @@ import java.util.*;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.primitive.*;
import ca.uhn.fhir.model.api.annotation.*;
import ca.uhn.fhir.model.base.composite.*;
#foreach ( $import in $imports )
import ${import};
@ -29,8 +30,8 @@ import ${import};
*/
@DatatypeDef(name="${className}")
public class ${className}
extends #{if}(${className}=="ResourceReferenceDt") BaseResourceReference #{else} BaseIdentifiableElement #{end}
implements ICompositeDatatype #{if}( ${className} == "IdentifierDt" || ${className} == "CodingDt" || ${className} == 'QuantityDt'), IQueryParameterType #{end}
extends #{if}( ${className}=="ResourceReferenceDt" || ${className}=="IdentifierDt" || ${className}=="CodingDt" || ${className}=='QuantityDt') Base${className} #{else} BaseIdentifiableElement #{end}
implements ICompositeDatatype
{
/**
@ -166,70 +167,6 @@ public class ${className}
setUnits(theUnits);
}
@Override
public void setValueAsQueryToken(String theQualifier, String theValue) {
setComparator((BoundCodeDt<QuantityCompararatorEnum>) null);
setCode((CodeDt) null);
setSystem((UriDt) null);
setUnits((StringDt) null);
setValue((DecimalDt) null);
if (theValue == null) {
return;
}
String[] parts = theValue.split("\\|");
if (parts.length > 0 && StringUtils.isNotBlank(parts[0])) {
if (parts[0].startsWith("<=")) {
setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
setValue(new BigDecimal(parts[0].substring(2)));
} else if (parts[0].startsWith("<")) {
setComparator(QuantityCompararatorEnum.LESSTHAN);
setValue(new BigDecimal(parts[0].substring(1)));
} else if (parts[0].startsWith(">=")) {
setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
setValue(new BigDecimal(parts[0].substring(2)));
} else if (parts[0].startsWith(">")) {
setComparator(QuantityCompararatorEnum.GREATERTHAN);
setValue(new BigDecimal(parts[0].substring(1)));
} else {
setValue(new BigDecimal(parts[0]));
}
}
if (parts.length > 1 && StringUtils.isNotBlank(parts[1])) {
setSystem(parts[1]);
}
if (parts.length > 2 && StringUtils.isNotBlank(parts[2])) {
setUnits(parts[2]);
}
}
@Override
public String getValueAsQueryToken() {
StringBuilder b= new StringBuilder();
if (getComparator() != null) {
b.append(getComparator().getValue());
}
if (!getValue().isEmpty()) {
b.append(getValue().getValueAsString());
}
b.append('|');
if (!getSystem().isEmpty()) {
b.append(getSystem().getValueAsString());
}
b.append('|');
if (!getUnits().isEmpty()) {
b.append(getUnits().getValueAsString());
}
return b.toString();
}
@Override
public String getQueryParameterQualifier() {
return null;
}
#end
#if ( ${className} == "ResourceReferenceDt" )
/**
@ -279,140 +216,7 @@ public class ${className}
#########################
### Type-specific methods
#########################
#if ( ${className} == "CodingDt" )
/**
* Returns true if <code>this</code> Coding has the same {@link CodingDt#[[#]]#getCode() Code}
* and {@link CodingDt#[[#]]#getSystem() system} (as compared by simple equals comparison).
* Does not compare other Codes (e.g. {@link CodingDt#[[#]]#getUse() use}) or any extensions.
*/
public boolean matchesSystemAndCode(CodingDt theCoding) {
if (theCoding == null) {
return false;
}
return getCode().equals(theCoding.getCode()) && getSystem().equals(theCoding.getSystem());
}
/**
* {@inheritDoc}
*/
@Override
public String getValueAsQueryToken() {
if (org.apache.commons.lang3.StringUtils.isNotBlank(getSystem().getValueAsString())) {
return getSystem().getValueAsString() + '|' + getCode().getValueAsString();
} else {
return getCode().getValueAsString();
}
}
/**
* {@inheritDoc}
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = theParameter.indexOf('|');
if (barIndex != -1) {
setSystem(new UriDt(theParameter.substring(0, barIndex)));
setCode(theParameter.substring(barIndex + 1));
} else {
setCode(theParameter);
}
}
@Override
public String getQueryParameterQualifier() {
return null;
}
#end
#if ( ${className} == "HumanNameDt" )
/**
* Returns all repetitions of {@link ${hash}getFamily() family name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getFamilyAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getFamily());
}
/**
* Returns all repetitions of {@link ${hash}getGiven() given name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getGivenAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getGiven());
}
/**
* Returns all repetitions of {@link ${hash}getPrefix() prefix name} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getPrefixAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getPrefix());
}
/**
* Returns all repetitions of {@link ${hash}Suffix() suffix} as a space separated string
*
* @see DatatypeUtil${hash}joinStringsSpaceSeparated(List)
*/
public String getSuffixAsSingleString() {
return ca.uhn.fhir.util.DatatypeUtil.joinStringsSpaceSeparated(getSuffix());
}
#end
#if ( ${className} == "IdentifierDt" )
/**
* Returns true if <code>this</code> identifier has the same {@link IdentifierDt#[[#]]#getValue() value}
* and {@link IdentifierDt#[[#]]#getSystem() system} (as compared by simple equals comparison).
* Does not compare other values (e.g. {@link IdentifierDt#[[#]]#getUse() use}) or any extensions.
*/
public boolean matchesSystemAndValue(IdentifierDt theIdentifier) {
if (theIdentifier == null) {
return false;
}
return getValue().equals(theIdentifier.getValue()) && getSystem().equals(theIdentifier.getSystem());
}
/**
* {@inheritDoc}
*/
@Override
public String getValueAsQueryToken() {
if (org.apache.commons.lang3.StringUtils.isNotBlank(getSystem().getValueAsString())) {
return getSystem().getValueAsString() + '|' + getValue().getValueAsString();
} else {
return getValue().getValueAsString();
}
}
/**
* {@inheritDoc}
*/
@Override
public void setValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = theParameter.indexOf('|');
if (barIndex != -1) {
setSystem(new UriDt(theParameter.substring(0, barIndex)));
setValue(theParameter.substring(barIndex + 1));
} else {
setValue(theParameter);
}
}
@Override
public String getQueryParameterQualifier() {
return null;
}
#end
#if ( ${className} == "ResourceReferenceDt" )
@Override
public String toString() {
org.apache.commons.lang3.builder.ToStringBuilder b = new org.apache.commons.lang3.builder.ToStringBuilder(this, org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE);
b.append("reference", getReference().getValueAsString());
b.append("loaded", getResource()!=null);
return b.toString();
}
#end
#childExtensionTypes( $childExtensionTypes )