Fix #315 - Allow declaring of custom types for specific profiles
This commit is contained in:
parent
5895881fa5
commit
1adfc4b4d9
|
@ -0,0 +1,7 @@
|
||||||
|
package example;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.Observation;
|
||||||
|
|
||||||
|
public class CustomObservation extends Observation {
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
public class Extensions {
|
public class ExtensionsDstu2 {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static void main(String[] args) throws DataFormatException, IOException {
|
public static void main(String[] args) throws DataFormatException, IOException {
|
|
@ -0,0 +1,140 @@
|
||||||
|
package example;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Extension;
|
||||||
|
import org.hl7.fhir.dstu3.model.HumanName;
|
||||||
|
import org.hl7.fhir.dstu3.model.Identifier.IdentifierUse;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
|
|
||||||
|
public class ExtensionsDstu3 {
|
||||||
|
|
||||||
|
public void customType() {
|
||||||
|
|
||||||
|
IGenericClient client = FhirContext.forDstu3().newRestfulGenericClient("http://foo");
|
||||||
|
|
||||||
|
//START SNIPPET: customTypeClientSimple
|
||||||
|
// Create an example patient
|
||||||
|
MyPatient custPatient = new MyPatient();
|
||||||
|
custPatient.addName().addFamily("Smith").addGiven("John");
|
||||||
|
custPatient.setPetName(new StringType("Rover")); // populate the extension
|
||||||
|
|
||||||
|
// Create the resource like normal
|
||||||
|
client.create().resource(custPatient).execute();
|
||||||
|
|
||||||
|
// You can also read the resource back like normal
|
||||||
|
custPatient = client.read().resource(MyPatient.class).withId("123").execute();
|
||||||
|
//END SNIPPET: customTypeClientSimple
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void customTypeDeclared() {
|
||||||
|
|
||||||
|
|
||||||
|
//START SNIPPET: customTypeClientDeclared
|
||||||
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
|
||||||
|
// Instruct the context that if it receives a resource which
|
||||||
|
// claims to conform to the given profile (by URL), it should
|
||||||
|
// use the MyPatient type to parse this resource
|
||||||
|
ctx.setDefaultTypeForProfile("http://example.com/StructureDefinition/mypatient", MyPatient.class);
|
||||||
|
|
||||||
|
// You can declare as many default types as you like
|
||||||
|
ctx.setDefaultTypeForProfile("http://foo.com/anotherProfile", CustomObservation.class);
|
||||||
|
|
||||||
|
// Create a client
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu3");
|
||||||
|
|
||||||
|
// You can also read the resource back like normal
|
||||||
|
Patient patient = client.read().resource(Patient.class).withId("123").execute();
|
||||||
|
if (patient instanceof MyPatient) {
|
||||||
|
// If the server supplied a resource which declared to conform
|
||||||
|
// to the given profile, MyPatient will have been returned so
|
||||||
|
// process it differently..
|
||||||
|
}
|
||||||
|
|
||||||
|
//END SNIPPET: customTypeClientDeclared
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static void main(String[] args) throws DataFormatException, IOException {
|
||||||
|
|
||||||
|
|
||||||
|
// START SNIPPET: resourceExtension
|
||||||
|
// Create an example patient
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
|
||||||
|
|
||||||
|
// Create an extension
|
||||||
|
Extension ext = new Extension();
|
||||||
|
ext.setUrl("http://example.com/extensions#someext");
|
||||||
|
ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
|
||||||
|
|
||||||
|
// Add the extension to the resource
|
||||||
|
patient.addExtension(ext);
|
||||||
|
//END SNIPPET: resourceExtension
|
||||||
|
|
||||||
|
|
||||||
|
//START SNIPPET: resourceStringExtension
|
||||||
|
// Continuing the example from above, we will add a name to the patient, and then
|
||||||
|
// add an extension to part of that name
|
||||||
|
HumanName name = patient.addName();
|
||||||
|
name.addFamily("Shmoe");
|
||||||
|
|
||||||
|
// Add a new "given name", which is of type String
|
||||||
|
StringType given = name.addGivenElement();
|
||||||
|
given.setValue("Joe");
|
||||||
|
|
||||||
|
// Create an extension and add it to the String
|
||||||
|
Extension givenExt = new Extension("http://examples.com#moreext", new StringType("Hello"));
|
||||||
|
given.addExtension(givenExt);
|
||||||
|
//END SNIPPET: resourceStringExtension
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
String output = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||||
|
System.out.println(output);
|
||||||
|
|
||||||
|
|
||||||
|
//START SNIPPET: parseExtension
|
||||||
|
// Get all extensions (modifier or not) for a given URL
|
||||||
|
List<Extension> resourceExts = patient.getExtensionsByUrl("http://fooextensions.com#exts");
|
||||||
|
|
||||||
|
// Get all non-modifier extensions regardless of URL
|
||||||
|
List<Extension> nonModExts = patient.getExtension();
|
||||||
|
|
||||||
|
//Get all non-modifier extensions regardless of URL
|
||||||
|
List<Extension> modExts = patient.getModifierExtension();
|
||||||
|
//END SNIPPET: parseExtension
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
//START SNIPPET: subExtension
|
||||||
|
Patient patient = new Patient();
|
||||||
|
|
||||||
|
// Add an extension (initially with no contents) to the resource
|
||||||
|
Extension parent = new Extension("http://example.com#parent");
|
||||||
|
patient.addExtension(parent);
|
||||||
|
|
||||||
|
// Add two extensions as children to the parent extension
|
||||||
|
Extension child1 = new Extension("http://example.com#childOne", new StringType("value1"));
|
||||||
|
parent.addExtension(child1);
|
||||||
|
|
||||||
|
Extension child2 = new Extension("http://example.com#chilwo", new StringType("value1"));
|
||||||
|
parent.addExtension(child2);
|
||||||
|
//END SNIPPET: subExtension
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,13 +4,14 @@ package example;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|
||||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +26,8 @@ import ca.uhn.fhir.util.ElementUtil;
|
||||||
@ResourceDef(name="Patient", profile="http://example.com/StructureDefinition/mypatient")
|
@ResourceDef(name="Patient", profile="http://example.com/StructureDefinition/mypatient")
|
||||||
public class MyPatient extends Patient {
|
public class MyPatient extends Patient {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each extension is defined in a field. Any valid HAPI Data Type
|
* Each extension is defined in a field. Any valid HAPI Data Type
|
||||||
* can be used for the field type. Note that the [name=""] attribute
|
* can be used for the field type. Note that the [name=""] attribute
|
||||||
|
@ -34,7 +37,7 @@ public class MyPatient extends Patient {
|
||||||
@Child(name="petName")
|
@Child(name="petName")
|
||||||
@Extension(url="http://example.com/dontuse#petname", definedLocally=false, isModifier=false)
|
@Extension(url="http://example.com/dontuse#petname", definedLocally=false, isModifier=false)
|
||||||
@Description(shortDefinition="The name of the patient's favourite pet")
|
@Description(shortDefinition="The name of the patient's favourite pet")
|
||||||
private StringDt myPetName;
|
private StringType myPetName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The second example extension uses a List type to provide
|
* The second example extension uses a List type to provide
|
||||||
|
@ -46,7 +49,7 @@ public class MyPatient extends Patient {
|
||||||
@Child(name="importantDates", max=Child.MAX_UNLIMITED)
|
@Child(name="importantDates", max=Child.MAX_UNLIMITED)
|
||||||
@Extension(url="http://example.com/dontuse#importantDates", definedLocally=false, isModifier=true)
|
@Extension(url="http://example.com/dontuse#importantDates", definedLocally=false, isModifier=true)
|
||||||
@Description(shortDefinition="Some dates of note for this patient")
|
@Description(shortDefinition="Some dates of note for this patient")
|
||||||
private List<DateTimeDt> myImportantDates;
|
private List<DateTimeType> myImportantDates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It is important to override the isEmpty() method, adding a check for any
|
* It is important to override the isEmpty() method, adding a check for any
|
||||||
|
@ -67,28 +70,28 @@ public class MyPatient extends Patient {
|
||||||
********/
|
********/
|
||||||
|
|
||||||
/** Getter for important dates */
|
/** Getter for important dates */
|
||||||
public List<DateTimeDt> getImportantDates() {
|
public List<DateTimeType> getImportantDates() {
|
||||||
if (myImportantDates==null) {
|
if (myImportantDates==null) {
|
||||||
myImportantDates = new ArrayList<DateTimeDt>();
|
myImportantDates = new ArrayList<DateTimeType>();
|
||||||
}
|
}
|
||||||
return myImportantDates;
|
return myImportantDates;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Getter for pet name */
|
/** Getter for pet name */
|
||||||
public StringDt getPetName() {
|
public StringType getPetName() {
|
||||||
if (myPetName == null) {
|
if (myPetName == null) {
|
||||||
myPetName = new StringDt();
|
myPetName = new StringType();
|
||||||
}
|
}
|
||||||
return myPetName;
|
return myPetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Setter for important dates */
|
/** Setter for important dates */
|
||||||
public void setImportantDates(List<DateTimeDt> theImportantDates) {
|
public void setImportantDates(List<DateTimeType> theImportantDates) {
|
||||||
myImportantDates = theImportantDates;
|
myImportantDates = theImportantDates;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Setter for pet name */
|
/** Setter for pet name */
|
||||||
public void setPetName(StringDt thePetName) {
|
public void setPetName(StringType thePetName) {
|
||||||
myPetName = thePetName;
|
myPetName = thePetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import ca.uhn.fhir.parser.IParser;
|
||||||
|
|
||||||
public class MyPatientUse {
|
public class MyPatientUse {
|
||||||
|
|
||||||
@ResourceDef
|
@ResourceDef()
|
||||||
public static class MyPatient extends Patient {
|
public static class MyPatient extends Patient {
|
||||||
|
|
||||||
@Child(name="petName")
|
@Child(name="petName")
|
||||||
|
|
|
@ -6,22 +6,16 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -5,6 +5,16 @@
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
<arguments>
|
<arguments>
|
||||||
|
@ -13,5 +23,7 @@
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.7
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<faceted-project>
|
||||||
|
<installed facet="java" version="1.7"/>
|
||||||
|
</faceted-project>
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.parser;
|
package ca.uhn.fhir.parser;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
|
@ -22,7 +23,10 @@ public class MultiVersionJsonParserTest {
|
||||||
String str = FhirContext.forDstu2().newJsonParser().encodeResourceToString(p);
|
String str = FhirContext.forDstu2().newJsonParser().encodeResourceToString(p);
|
||||||
ourLog.info(str);
|
ourLog.info(str);
|
||||||
|
|
||||||
assertThat(str, StringContains.containsString("{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://foo#ext\",\"valueQuantity\":{\"value\":2.2}}],\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]}"));
|
assertThat(str, stringContainsInOrder(
|
||||||
|
"{\"resourceType\":\"Patient\"",
|
||||||
|
"\"extension\":[{\"url\":\"http://foo#ext\",\"valueQuantity\":{\"value\":2.2}}]",
|
||||||
|
"\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.rest.client.IRestfulClientFactory;
|
||||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
import ca.uhn.fhir.util.VersionUtil;
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
|
@ -77,7 +78,9 @@ public class FhirContext {
|
||||||
|
|
||||||
private static final List<Class<? extends IBaseResource>> EMPTY_LIST = Collections.emptyList();
|
private static final List<Class<? extends IBaseResource>> EMPTY_LIST = Collections.emptyList();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContext.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContext.class);
|
||||||
|
private AddProfileTagEnum myAddProfileTagWhenEncoding = AddProfileTagEnum.ONLY_FOR_CUSTOM;
|
||||||
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
||||||
|
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<String, Class<? extends IBaseResource>>();
|
||||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||||
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
||||||
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
|
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
|
||||||
|
@ -144,6 +147,26 @@ public class FhirContext {
|
||||||
return getLocalizer().getMessage(FhirContext.class, "unknownResourceName", theResourceName, theVersion);
|
return getLocalizer().getMessage(FhirContext.class, "unknownResourceName", theResourceName, theVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When encoding resources, this setting configures the parser to include
|
||||||
|
* an entry in the resource's metadata section which indicates which profile(s) the
|
||||||
|
* resource claims to conform to. The default is {@link AddProfileTagEnum#ONLY_FOR_CUSTOM}.
|
||||||
|
*
|
||||||
|
* @see #setAddProfileTagWhenEncoding(AddProfileTagEnum) for more information
|
||||||
|
*/
|
||||||
|
public AddProfileTagEnum getAddProfileTagWhenEncoding() {
|
||||||
|
return myAddProfileTagWhenEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default resource type for the given profile
|
||||||
|
*
|
||||||
|
* @see #setDefaultTypeForProfile(String, Class)
|
||||||
|
*/
|
||||||
|
public Class<? extends IBaseResource> getDefaultTypeForProfile(String theProfile) {
|
||||||
|
return myDefaultTypeForProfile.get(theProfile);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||||
* for extending the core library.
|
* for extending the core library.
|
||||||
|
@ -298,14 +321,6 @@ public class FhirContext {
|
||||||
return myIdToResourceDefinition.values();
|
return myIdToResourceDefinition.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the restful client factory
|
|
||||||
* @param theRestfulClientFactory
|
|
||||||
*/
|
|
||||||
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
|
||||||
this.myRestfulClientFactory = theRestfulClientFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the restful client factory. If no factory has been set, this will be initialized with
|
* Get the restful client factory. If no factory has been set, this will be initialized with
|
||||||
* a new ApacheRestfulClientFactory.
|
* a new ApacheRestfulClientFactory.
|
||||||
|
@ -326,6 +341,17 @@ public class FhirContext {
|
||||||
return myVersion;
|
return myVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if any default types for specific profiles have been defined
|
||||||
|
* within this context.
|
||||||
|
*
|
||||||
|
* @see #setDefaultTypeForProfile(String, Class)
|
||||||
|
* @see #getDefaultTypeForProfile(String)
|
||||||
|
*/
|
||||||
|
public boolean hasDefaultTypeForProfile() {
|
||||||
|
return !myDefaultTypeForProfile.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should be considered experimental and will likely change in future releases
|
* This method should be considered experimental and will likely change in future releases
|
||||||
* of HAPI. Use with caution!
|
* of HAPI. Use with caution!
|
||||||
|
@ -473,6 +499,50 @@ public class FhirContext {
|
||||||
return classToElementDefinition;
|
return classToElementDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When encoding resources, this setting configures the parser to include
|
||||||
|
* an entry in the resource's metadata section which indicates which profile(s) the
|
||||||
|
* resource claims to conform to. The default is {@link AddProfileTagEnum#ONLY_FOR_CUSTOM}.
|
||||||
|
* <p>
|
||||||
|
* This feature is intended for situations where custom resource types are being used,
|
||||||
|
* avoiding the need to manually add profile declarations for these custom types.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* See <a href="http://jamesagnew.gihhub.io/hapi-fhir/doc_extensions.html">Profiling and Extensions</a>
|
||||||
|
* for more information on using custom types.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note that this feature automatically adds the profile, but leaves any profile tags
|
||||||
|
* which have been manually added in place as well.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param theAddProfileTagWhenEncoding
|
||||||
|
* The add profile mode (must not be <code>null</code>)
|
||||||
|
*/
|
||||||
|
public void setAddProfileTagWhenEncoding(AddProfileTagEnum theAddProfileTagWhenEncoding) {
|
||||||
|
Validate.notNull(theAddProfileTagWhenEncoding, "theAddProfileTagWhenEncoding must not be null");
|
||||||
|
myAddProfileTagWhenEncoding = theAddProfileTagWhenEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default type which will be used when parsing a resource that is found to be
|
||||||
|
* of the given profile.
|
||||||
|
* <p>
|
||||||
|
* For example, this method is invoked with the profile string of
|
||||||
|
* <code>"http://example.com/some_patient_profile"</code> and the type of <code>MyPatient.class</code>,
|
||||||
|
* if the parser is parsing a resource and finds that it declares that it conforms to that profile,
|
||||||
|
* the <code>MyPatient</code> type will be used unless otherwise specified.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param theProfile The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be <code>null</code> or empty.
|
||||||
|
* @param theClass The resource type. Must not be <code>null</code> or empty.
|
||||||
|
*/
|
||||||
|
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
||||||
|
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
||||||
|
Validate.notNull(theClass, "theProfile must not be null");
|
||||||
|
myDefaultTypeForProfile.put(theProfile, theClass);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||||
* caution
|
* caution
|
||||||
|
@ -495,6 +565,14 @@ public class FhirContext {
|
||||||
myParserErrorHandler = theParserErrorHandler;
|
myParserErrorHandler = theParserErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the restful client factory
|
||||||
|
* @param theRestfulClientFactory
|
||||||
|
*/
|
||||||
|
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
||||||
|
this.myRestfulClientFactory = theRestfulClientFactory;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "cast" })
|
@SuppressWarnings({ "cast" })
|
||||||
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
||||||
if (theResourceTypes == null) {
|
if (theResourceTypes == null) {
|
||||||
|
@ -508,21 +586,28 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU1}
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU1 DSTU1}
|
||||||
*/
|
*/
|
||||||
public static FhirContext forDstu1() {
|
public static FhirContext forDstu1() {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU1);
|
return new FhirContext(FhirVersionEnum.DSTU1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU 2}
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU2}
|
||||||
*/
|
*/
|
||||||
public static FhirContext forDstu2() {
|
public static FhirContext forDstu2() {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2);
|
return new FhirContext(FhirVersionEnum.DSTU2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU3 DSTU 3}
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_HL7ORG DSTU2} (using the Reference Implementation Structures)
|
||||||
|
*/
|
||||||
|
public static FhirContext forDstu2Hl7Org() {
|
||||||
|
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU3 DSTU3}
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
@ -530,10 +615,6 @@ public class FhirContext {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU3);
|
return new FhirContext(FhirVersionEnum.DSTU3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FhirContext forDstu2Hl7Org() {
|
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
||||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||||
retVal.add(theResourceType);
|
retVal.add(theResourceType);
|
||||||
|
|
|
@ -683,6 +683,14 @@ class ModelScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Class<? extends IBaseResource> builtInType = myNameToResourceType.get(resourceName.toLowerCase());
|
||||||
|
boolean standardType = builtInType != null && builtInType.equals(theClass) == true;
|
||||||
|
if (primaryNameProvider) {
|
||||||
|
if (builtInType != null && builtInType.equals(theClass) == false) {
|
||||||
|
primaryNameProvider = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String resourceId = resourceDefinition.id();
|
String resourceId = resourceDefinition.id();
|
||||||
if (!isBlank(resourceId)) {
|
if (!isBlank(resourceId)) {
|
||||||
if (myIdToResourceDefinition.containsKey(resourceId)) {
|
if (myIdToResourceDefinition.containsKey(resourceId)) {
|
||||||
|
@ -691,7 +699,7 @@ class ModelScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(myContext, resourceName, theClass, resourceDefinition, isStandardType(theClass));
|
RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(myContext, resourceName, theClass, resourceDefinition, standardType);
|
||||||
myClassToElementDefinitions.put(theClass, resourceDef);
|
myClassToElementDefinitions.put(theClass, resourceDef);
|
||||||
if (primaryNameProvider) {
|
if (primaryNameProvider) {
|
||||||
if (resourceDef.getStructureVersion() == myVersion) {
|
if (resourceDef.getStructureVersion() == myVersion) {
|
||||||
|
|
|
@ -155,10 +155,6 @@ public class RuntimeResourceDefinition extends BaseRuntimeElementCompositeDefini
|
||||||
return "Bundle".equals(getName());
|
return "Bundle".equals(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStandardProfile() {
|
|
||||||
return myResourceProfile.startsWith("http://hl7.org/fhir/profiles");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
|
public void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
|
||||||
super.sealAndInitialize(theContext, theClassToElementDefinitions);
|
super.sealAndInitialize(theContext, theClassToElementDefinitions);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ca.uhn.fhir.model.api;
|
package ca.uhn.fhir.model.api;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR - Core Library
|
* HAPI FHIR - Core Library
|
||||||
|
@ -62,6 +64,15 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode
|
||||||
*/
|
*/
|
||||||
CodeDt getLanguage();
|
CodeDt getLanguage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a view of the {@link #getResourceMetadata() resource metadata} map.
|
||||||
|
* Note that getters from this map return immutable objects, but the <code>addFoo()</code>
|
||||||
|
* and <code>setFoo()</code> methods may be used to modify metadata.
|
||||||
|
*
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
IBaseMetaType getMeta();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the metadata map for this object, creating it if neccesary. Metadata entries are used to get/set feed bundle entries, such as the resource version, or the last updated timestamp.
|
* Returns the metadata map for this object, creating it if neccesary. Metadata entries are used to get/set feed bundle entries, such as the resource version, or the last updated timestamp.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -72,10 +83,23 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode
|
||||||
*/
|
*/
|
||||||
ResourceMetadataMap getResourceMetadata();
|
ResourceMetadataMap getResourceMetadata();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String representing the name of this Resource. This return value is not used for anything by HAPI itself, but is provided as a convenience to developers using the API.
|
||||||
|
*
|
||||||
|
* @return the name of this resource, e.g. "Patient", or "Observation"
|
||||||
|
*/
|
||||||
|
String getResourceName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FHIR version represented by this structure
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ca.uhn.fhir.context.FhirVersionEnum getStructureFhirVersionEnum();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the narrative block for this resource
|
* Returns the narrative block for this resource
|
||||||
*/
|
*/
|
||||||
BaseNarrativeDt getText();
|
BaseNarrativeDt<?> getText();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the ID of this resource. Note that this identifier is the URL (or a portion of the URL) used to access this resource, and is not the same thing as any business identifiers stored within the
|
* Sets the ID of this resource. Note that this identifier is the URL (or a portion of the URL) used to access this resource, and is not the same thing as any business identifiers stored within the
|
||||||
|
@ -99,16 +123,4 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode
|
||||||
*/
|
*/
|
||||||
void setResourceMetadata(ResourceMetadataMap theMap);
|
void setResourceMetadata(ResourceMetadataMap theMap);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representing the name of this Resource. This return value is not used for anything by HAPI itself, but is provided as a convenience to developers using the API.
|
|
||||||
*
|
|
||||||
* @return the name of this resource, e.g. "Patient", or "Observation"
|
|
||||||
*/
|
|
||||||
String getResourceName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the FHIR version represented by this structure
|
|
||||||
*/
|
|
||||||
public ca.uhn.fhir.context.FhirVersionEnum getStructureFhirVersionEnum();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.net.URI;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single tag
|
* A single tag
|
||||||
|
@ -34,7 +35,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
* {@link #getScheme() scheme} and
|
* {@link #getScheme() scheme} and
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class Tag extends BaseElement implements IElement {
|
public class Tag extends BaseElement implements IElement, IBaseCoding {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ -59,10 +60,6 @@ public class Tag extends BaseElement implements IElement {
|
||||||
private String myScheme;
|
private String myScheme;
|
||||||
private String myTerm;
|
private String myTerm;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Tags will become immutable in a future release, so this constructor should not be used.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Tag() {
|
public Tag() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +146,7 @@ public class Tag extends BaseElement implements IElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the label and returns a reference to this tag
|
* Sets the label and returns a reference to this tag
|
||||||
*
|
|
||||||
* @deprecated Tags will become immutable in a future release of HAPI in order to facilitate
|
|
||||||
* ensuring that the TagList acts as an unordered set. Use the constructor to set this field when creating a new
|
|
||||||
* tag object
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public Tag setLabel(String theLabel) {
|
public Tag setLabel(String theLabel) {
|
||||||
myLabel = theLabel;
|
myLabel = theLabel;
|
||||||
return this;
|
return this;
|
||||||
|
@ -162,12 +154,7 @@ public class Tag extends BaseElement implements IElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scheme and returns a reference to this tag
|
* Sets the scheme and returns a reference to this tag
|
||||||
*
|
|
||||||
* @deprecated Tags will become immutable in a future release of HAPI in order to facilitate
|
|
||||||
* ensuring that the TagList acts as an unordered set. Use the constructor to set this field when creating a new
|
|
||||||
* tag object
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public Tag setScheme(String theScheme) {
|
public Tag setScheme(String theScheme) {
|
||||||
myScheme = theScheme;
|
myScheme = theScheme;
|
||||||
return this;
|
return this;
|
||||||
|
@ -175,12 +162,7 @@ public class Tag extends BaseElement implements IElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the term and returns a reference to this tag
|
* Sets the term and returns a reference to this tag
|
||||||
*
|
|
||||||
* @deprecated Tags will become immutable in a future release of HAPI in order to facilitate
|
|
||||||
* ensuring that the TagList acts as an unordered set. Use the constructor to set this field when creating a new
|
|
||||||
* tag object
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public Tag setTerm(String theTerm) {
|
public Tag setTerm(String theTerm) {
|
||||||
myTerm = theTerm;
|
myTerm = theTerm;
|
||||||
return this;
|
return this;
|
||||||
|
@ -207,4 +189,37 @@ public class Tag extends BaseElement implements IElement {
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return getTerm();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplay() {
|
||||||
|
return getLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return getScheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setCode(String theTerm) {
|
||||||
|
setTerm(myTerm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setDisplay(String theLabel) {
|
||||||
|
setLabel(theLabel);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setSystem(String theScheme) {
|
||||||
|
setScheme(theScheme);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,10 @@ public @interface ResourceDef {
|
||||||
/**
|
/**
|
||||||
* The URL indicating the profile for this resource definition. If specified, this URL will be
|
* The URL indicating the profile for this resource definition. If specified, this URL will be
|
||||||
* automatically added to the meta tag when the resource is serialized.
|
* automatically added to the meta tag when the resource is serialized.
|
||||||
|
* <p>
|
||||||
|
* This URL should be fully qualified to indicate the complete URL of
|
||||||
|
* the profile being used, e.g. <code>http://example.com/fhir/StructureDefiniton/some_profile</code>
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
String profile() default "";
|
String profile() default "";
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,14 @@ public abstract class BaseParser implements IParser {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseParser.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseParser.class);
|
||||||
|
|
||||||
private IIdType myEncodeForceResourceId;
|
|
||||||
private ContainedResources myContainedResources;
|
private ContainedResources myContainedResources;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
|
private Set<String> myDontEncodeElements;
|
||||||
|
private boolean myDontEncodeElementsIncludesStars;
|
||||||
private Set<String> myEncodeElements;
|
private Set<String> myEncodeElements;
|
||||||
private Set<String> myEncodeElementsAppliesToResourceTypes;
|
private Set<String> myEncodeElementsAppliesToResourceTypes;
|
||||||
private boolean myEncodeElementsIncludesStars;
|
private boolean myEncodeElementsIncludesStars;
|
||||||
|
private IIdType myEncodeForceResourceId;
|
||||||
private IParserErrorHandler myErrorHandler;
|
private IParserErrorHandler myErrorHandler;
|
||||||
private boolean myOmitResourceId;
|
private boolean myOmitResourceId;
|
||||||
private String myServerBaseUrl;
|
private String myServerBaseUrl;
|
||||||
|
@ -91,10 +93,6 @@ public abstract class BaseParser implements IParser {
|
||||||
private boolean mySummaryMode;
|
private boolean mySummaryMode;
|
||||||
private boolean mySuppressNarratives;
|
private boolean mySuppressNarratives;
|
||||||
|
|
||||||
private Set<String> myDontEncodeElements;
|
|
||||||
|
|
||||||
private boolean myDontEncodeElementsIncludesStars;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -439,6 +437,47 @@ public abstract class BaseParser implements IParser {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
protected <T extends IPrimitiveType<String>> List<T> getProfileTagsForEncoding(IBaseResource theResource, List<T> theProfiles) {
|
||||||
|
switch (myContext.getAddProfileTagWhenEncoding()) {
|
||||||
|
case NEVER:
|
||||||
|
return theProfiles;
|
||||||
|
case ONLY_FOR_CUSTOM:
|
||||||
|
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||||
|
if (resDef.isStandardType()) {
|
||||||
|
return theProfiles;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALWAYS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||||
|
RuntimeResourceDefinition nextDef = myContext.getResourceDefinition(theResource);
|
||||||
|
String profile = nextDef.getResourceProfile(myServerBaseUrl);
|
||||||
|
if (isNotBlank(profile)) {
|
||||||
|
for (T next : theProfiles) {
|
||||||
|
if (profile.equals(next.getValue())) {
|
||||||
|
return theProfiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<T> newList = new ArrayList<T>();
|
||||||
|
newList.addAll(theProfiles);
|
||||||
|
|
||||||
|
BaseRuntimeElementDefinition<?> idElement = myContext.getElementDefinition("id");
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T newId = (T) idElement.newInstance();
|
||||||
|
newId.setValue(profile);
|
||||||
|
|
||||||
|
newList.add(newId);
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return theProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded
|
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded
|
||||||
* values.
|
* values.
|
||||||
|
@ -595,6 +634,17 @@ public abstract class BaseParser implements IParser {
|
||||||
filterCodingsWithNoCodeOrSystem(metaValue.getTag());
|
filterCodingsWithNoCodeOrSystem(metaValue.getTag());
|
||||||
filterCodingsWithNoCodeOrSystem(metaValue.getSecurity());
|
filterCodingsWithNoCodeOrSystem(metaValue.getSecurity());
|
||||||
|
|
||||||
|
List<? extends IPrimitiveType<String>> newProfileList = getProfileTagsForEncoding(theResource, metaValue.getProfile());
|
||||||
|
List<? extends IPrimitiveType<String>> oldProfileList = metaValue.getProfile();
|
||||||
|
if (oldProfileList != newProfileList) {
|
||||||
|
oldProfileList.clear();
|
||||||
|
for (IPrimitiveType<String> next : newProfileList) {
|
||||||
|
if (isNotBlank(next.getValue())) {
|
||||||
|
metaValue.addProfile(next.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldAddSubsettedTag()) {
|
if (shouldAddSubsettedTag()) {
|
||||||
IBaseCoding coding = metaValue.addTag();
|
IBaseCoding coding = metaValue.addTag();
|
||||||
coding.setCode(Constants.TAG_SUBSETTED_CODE);
|
coding.setCode(Constants.TAG_SUBSETTED_CODE);
|
||||||
|
@ -748,11 +798,11 @@ public abstract class BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
|
protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
|
||||||
List<T> securityLabels = key.get(resource);
|
List<? extends T> securityLabels = key.get(resource);
|
||||||
if (securityLabels == null) {
|
if (securityLabels == null) {
|
||||||
securityLabels = Collections.emptyList();
|
securityLabels = Collections.emptyList();
|
||||||
}
|
}
|
||||||
return securityLabels;
|
return new ArrayList<T>(securityLabels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean hasExtensions(IBase theElement) {
|
static boolean hasExtensions(IBase theElement) {
|
||||||
|
|
|
@ -222,7 +222,8 @@ public interface IParser {
|
||||||
* <li><b>Patient</b> - Don't encode patient and all its children</li>
|
* <li><b>Patient</b> - Don't encode patient and all its children</li>
|
||||||
* <li><b>Patient.name</b> - Don't encode the patient's name</li>
|
* <li><b>Patient.name</b> - Don't encode the patient's name</li>
|
||||||
* <li><b>Patient.name.family</b> - Don't encode the patient's family name</li>
|
* <li><b>Patient.name.family</b> - Don't encode the patient's family name</li>
|
||||||
* <li><b>*.text</b> - Don't encode the text element on any resource (only the very first position may contain a wildcard)</li>
|
* <li><b>*.text</b> - Don't encode the text element on any resource (only the very first position may contain a
|
||||||
|
* wildcard)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* DSTU2 note: Note that values including meta, such as <code>Patient.meta</code>
|
* DSTU2 note: Note that values including meta, such as <code>Patient.meta</code>
|
||||||
|
@ -244,7 +245,8 @@ public interface IParser {
|
||||||
* <li><b>Patient</b> - Encode patient and all its children</li>
|
* <li><b>Patient</b> - Encode patient and all its children</li>
|
||||||
* <li><b>Patient.name</b> - Encode only the patient's name</li>
|
* <li><b>Patient.name</b> - Encode only the patient's name</li>
|
||||||
* <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
|
* <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
|
||||||
* <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a wildcard)</li>
|
* <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a
|
||||||
|
* wildcard)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param theEncodeElements
|
* @param theEncodeElements
|
||||||
|
|
|
@ -838,7 +838,9 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
// Object securityLabelRawObj =
|
// Object securityLabelRawObj =
|
||||||
|
|
||||||
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||||
List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
||||||
|
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
||||||
|
|
||||||
TagList tags = getMetaTagsForEncoding(resource);
|
TagList tags = getMetaTagsForEncoding(resource);
|
||||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||||
IdDt resourceId = resource.getId();
|
IdDt resourceId = resource.getId();
|
||||||
|
@ -854,7 +856,7 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
if (profiles != null && profiles.isEmpty() == false) {
|
if (profiles != null && profiles.isEmpty() == false) {
|
||||||
theEventWriter.writeStartArray("profile");
|
theEventWriter.writeStartArray("profile");
|
||||||
for (IdDt profile : profiles) {
|
for (IIdType profile : profiles) {
|
||||||
if (profile != null && isNotBlank(profile.getValue())) {
|
if (profile != null && isNotBlank(profile.getValue())) {
|
||||||
theEventWriter.write(profile.getValue());
|
theEventWriter.write(profile.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.hl7.fhir.instance.model.api.IBaseElement;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseXhtml;
|
import org.hl7.fhir.instance.model.api.IBaseXhtml;
|
||||||
|
@ -1433,6 +1434,11 @@ class ParserState<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populateTarget() {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ContainedResourcesStateHl7Org extends PreResourceState {
|
private class ContainedResourcesStateHl7Org extends PreResourceState {
|
||||||
|
@ -1464,6 +1470,11 @@ class ParserState<T> {
|
||||||
def.getChildByName("contained").getMutator().addValue(preResCurrentElement, res);
|
def.getChildByName("contained").getMutator().addValue(preResCurrentElement, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populateTarget() {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DeclaredExtensionState extends BaseState {
|
private class DeclaredExtensionState extends BaseState {
|
||||||
|
@ -1969,6 +1980,8 @@ class ParserState<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void populateTarget();
|
||||||
|
|
||||||
public PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
|
public PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
|
||||||
super(thePreResourcesState);
|
super(thePreResourcesState);
|
||||||
Validate.notNull(theParentVersion);
|
Validate.notNull(theParentVersion);
|
||||||
|
@ -2045,6 +2058,40 @@ class ParserState<T> {
|
||||||
public void wereBack() {
|
public void wereBack() {
|
||||||
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
|
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
|
||||||
|
|
||||||
|
if (myContext.hasDefaultTypeForProfile()) {
|
||||||
|
IBaseMetaType meta = myInstance.getMeta();
|
||||||
|
Class<? extends IBaseResource> wantedProfileType = null;
|
||||||
|
String usedProfile = null;
|
||||||
|
for (IPrimitiveType<String> next : meta.getProfile()) {
|
||||||
|
if (isNotBlank(next.getValue())) {
|
||||||
|
wantedProfileType = myContext.getDefaultTypeForProfile(next.getValue());
|
||||||
|
if (wantedProfileType != null) {
|
||||||
|
usedProfile = next.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) {
|
||||||
|
if (myResourceType == null || myResourceType.isAssignableFrom(wantedProfileType)) {
|
||||||
|
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", new Object[] {myInstance.getClass().getName(), usedProfile, wantedProfileType});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This isn't the most efficient thing really.. If we want a specific
|
||||||
|
* type we just re-parse into that type. The problem is that we don't know
|
||||||
|
* until we've parsed the resource which type we want to use because the
|
||||||
|
* profile declarations are in the text of the resource itself.
|
||||||
|
*
|
||||||
|
* At some point it would be good to write code which can present a view
|
||||||
|
* of one type backed by another type and use that.
|
||||||
|
*/
|
||||||
|
IParser parser = myContext.newJsonParser();
|
||||||
|
String asString = parser.encodeResourceToString(myInstance);
|
||||||
|
myInstance = parser.parseResource(wantedProfileType, asString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FhirTerser terser = myContext.newTerser();
|
FhirTerser terser = myContext.newTerser();
|
||||||
terser.visit(myInstance, new IModelVisitor() {
|
terser.visit(myInstance, new IModelVisitor() {
|
||||||
|
|
||||||
|
@ -2114,6 +2161,7 @@ class ParserState<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
populateTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2141,14 +2189,19 @@ class ParserState<T> {
|
||||||
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
|
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||||
|
// super.enteringNewElement(theNamespaceUri, theLocalPart);
|
||||||
|
// populateTarget();
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
protected void populateTarget() {
|
||||||
super.enteringNewElement(theNamespaceUri, theLocalPart);
|
|
||||||
if (myEntry != null) {
|
if (myEntry != null) {
|
||||||
myEntry.setResource((IResource) getCurrentElement());
|
myEntry.setResource((IResource) getCurrentElement());
|
||||||
}
|
}
|
||||||
if (myMutator != null) {
|
if (myMutator != null) {
|
||||||
myMutator.addValue(myTarget, getCurrentElement());
|
myMutator.setValue(myTarget, getCurrentElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2192,10 +2245,9 @@ class ParserState<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
protected void populateTarget() {
|
||||||
super.enteringNewElement(theNamespaceUri, theLocalPart);
|
|
||||||
if (myMutator != null) {
|
if (myMutator != null) {
|
||||||
myMutator.addValue(myTarget, getCurrentElement());
|
myMutator.setValue(myTarget, getCurrentElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,16 +132,6 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
} catch (XMLStreamException e1) {
|
} catch (XMLStreamException e1) {
|
||||||
throw new DataFormatException(e1);
|
throw new DataFormatException(e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XMLEventReader streamReader;
|
|
||||||
// try {
|
|
||||||
// streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
|
||||||
// } catch (XMLStreamException e) {
|
|
||||||
// throw new DataFormatException(e);
|
|
||||||
// } catch (FactoryConfigurationError e) {
|
|
||||||
// throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
|
||||||
// }
|
|
||||||
// return streamReader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private XMLStreamWriter createXmlWriter(Writer theWriter) throws XMLStreamException {
|
private XMLStreamWriter createXmlWriter(Writer theWriter) throws XMLStreamException {
|
||||||
|
@ -433,8 +423,6 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
String bundleBaseUrl = theBundle.getLinkBase().getValue();
|
|
||||||
|
|
||||||
writeOptionalTagWithValue(theEventWriter, "type", theBundle.getType().getValue());
|
writeOptionalTagWithValue(theEventWriter, "type", theBundle.getType().getValue());
|
||||||
writeOptionalTagWithValue(theEventWriter, "total", theBundle.getTotalResults().getValueAsString());
|
writeOptionalTagWithValue(theEventWriter, "total", theBundle.getTotalResults().getValueAsString());
|
||||||
|
|
||||||
|
@ -841,7 +829,9 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
||||||
}
|
}
|
||||||
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||||
List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
||||||
|
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
||||||
|
|
||||||
TagList tags = getMetaTagsForEncoding((resource));
|
TagList tags = getMetaTagsForEncoding((resource));
|
||||||
|
|
||||||
if (super.shouldEncodeResourceMeta(resource) && ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) {
|
if (super.shouldEncodeResourceMeta(resource) && ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) {
|
||||||
|
@ -851,7 +841,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdDt profile : profiles) {
|
for (IIdType profile : profiles) {
|
||||||
theEventWriter.writeStartElement("profile");
|
theEventWriter.writeStartElement("profile");
|
||||||
theEventWriter.writeAttribute("value", profile.getValue());
|
theEventWriter.writeAttribute("value", profile.getValue());
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR - Core Library
|
* HAPI FHIR - Core Library
|
||||||
|
@ -21,9 +23,9 @@ package ca.uhn.fhir.rest.server;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RESTful server behaviour for automatically adding profile tags
|
* RESTful server behaviour for automatically adding profile tags when serializing resources
|
||||||
*
|
*
|
||||||
* @see RestfulServer#setAddProfileTag(AddProfileTagEnum)
|
* @see FhirContext#setAddProfileTagWhenEncoding(AddProfileTagEnum)
|
||||||
*/
|
*/
|
||||||
public enum AddProfileTagEnum {
|
public enum AddProfileTagEnum {
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +35,13 @@ public enum AddProfileTagEnum {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add any profile tags that returned resources appear to conform to
|
* Add any profile tags that returned resources appear to conform to
|
||||||
|
*
|
||||||
|
* @deprecated This mode causes even FHIR's default profiles to be exported in the
|
||||||
|
* resource metadata section. This is not generally expected behaviour from other
|
||||||
|
* systems and it offers no real benefit, so it will be removed at some point. This
|
||||||
|
* option was deprecated in HAPI 1.5
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
ALWAYS,
|
ALWAYS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,7 +48,9 @@ public interface IRestfulServerDefaults {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the setting for automatically adding profile tags
|
* @return Returns the setting for automatically adding profile tags
|
||||||
|
* @deprecated As of HAPI FHIR 1.5, this property has been moved to {@link FhirContext#setAddProfileTagWhenEncoding(AddProfileTagEnum)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
AddProfileTagEnum getAddProfileTag();
|
AddProfileTagEnum getAddProfileTag();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,7 +40,7 @@ public interface IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated);
|
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated);
|
||||||
|
|
||||||
void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
||||||
int theOffset, Integer theCount, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes);
|
int theOffset, Integer theCount, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes);
|
||||||
|
|
||||||
Bundle getDstu1Bundle();
|
Bundle getDstu1Bundle();
|
||||||
|
|
|
@ -74,6 +74,7 @@ import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.util.VersionUtil;
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
|
@ -93,7 +94,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
private static final ExceptionHandlingInterceptor DEFAULT_EXCEPTION_HANDLER = new ExceptionHandlingInterceptor();
|
private static final ExceptionHandlingInterceptor DEFAULT_EXCEPTION_HANDLER = new ExceptionHandlingInterceptor();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private AddProfileTagEnum myAddProfileTag;
|
|
||||||
private BundleInclusionRule myBundleInclusionRule = BundleInclusionRule.BASED_ON_INCLUDES;
|
private BundleInclusionRule myBundleInclusionRule = BundleInclusionRule.BASED_ON_INCLUDES;
|
||||||
private boolean myDefaultPrettyPrint = false;
|
private boolean myDefaultPrettyPrint = false;
|
||||||
private EncodingEnum myDefaultResponseEncoding = EncodingEnum.XML;
|
private EncodingEnum myDefaultResponseEncoding = EncodingEnum.XML;
|
||||||
|
@ -369,11 +369,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AddProfileTagEnum getAddProfileTag() {
|
|
||||||
return myAddProfileTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BundleInclusionRule getBundleInclusionRule() {
|
public BundleInclusionRule getBundleInclusionRule() {
|
||||||
return myBundleInclusionRule;
|
return myBundleInclusionRule;
|
||||||
|
@ -1117,10 +1112,13 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
*
|
*
|
||||||
* @param theAddProfileTag
|
* @param theAddProfileTag
|
||||||
* The behaviour enum (must not be null)
|
* The behaviour enum (must not be null)
|
||||||
|
* @deprecated As of HAPI FHIR 1.5, this property has been moved to {@link FhirContext#setAddProfileTagWhenEncoding(AddProfileTagEnum)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@CoverageIgnore
|
||||||
public void setAddProfileTag(AddProfileTagEnum theAddProfileTag) {
|
public void setAddProfileTag(AddProfileTagEnum theAddProfileTag) {
|
||||||
Validate.notNull(theAddProfileTag, "theAddProfileTag must not be null");
|
Validate.notNull(theAddProfileTag, "theAddProfileTag must not be null");
|
||||||
myAddProfileTag = theAddProfileTag;
|
myFhirContext.setAddProfileTagWhenEncoding(theAddProfileTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1394,4 +1392,13 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
return nextString.length() > 0 && (nextString.charAt(0) == '_' || nextString.charAt(0) == '$' || nextString.equals(Constants.URL_TOKEN_METADATA));
|
return nextString.length() > 0 && (nextString.charAt(0) == '_' || nextString.charAt(0) == '$' || nextString.equals(Constants.URL_TOKEN_METADATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated As of HAPI FHIR 1.5, this property has been moved to {@link FhirContext#setAddProfileTagWhenEncoding(AddProfileTagEnum)}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public AddProfileTagEnum getAddProfileTag() {
|
||||||
|
return myFhirContext.getAddProfileTagWhenEncoding();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -49,15 +48,12 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.api.Tag;
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
@ -77,36 +73,6 @@ public class RestfulServerUtils {
|
||||||
|
|
||||||
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<String>(Arrays.asList("Bundle", "*.text"));
|
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<String>(Arrays.asList("Bundle", "*.text"));
|
||||||
|
|
||||||
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
|
|
||||||
if (theResource instanceof IResource) {
|
|
||||||
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
|
||||||
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
|
||||||
String profile = nextDef.getResourceProfile(theServerBase);
|
|
||||||
if (isNotBlank(profile)) {
|
|
||||||
List<IdDt> newList = new ArrayList<IdDt>();
|
|
||||||
List<IdDt> existingList = ResourceMetadataKeyEnum.PROFILES.get((IResource) theResource);
|
|
||||||
if (existingList != null) {
|
|
||||||
newList.addAll(existingList);
|
|
||||||
}
|
|
||||||
newList.add(new IdDt(profile));
|
|
||||||
ResourceMetadataKeyEnum.PROFILES.put((IResource) theResource, newList);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
|
|
||||||
if (tl == null) {
|
|
||||||
tl = new TagList();
|
|
||||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
|
|
||||||
}
|
|
||||||
|
|
||||||
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
|
||||||
String profile = nextDef.getResourceProfile(theServerBase);
|
|
||||||
if (isNotBlank(profile)) {
|
|
||||||
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void configureResponseParser(RequestDetails theRequestDetails, IParser parser) {
|
public static void configureResponseParser(RequestDetails theRequestDetails, IParser parser) {
|
||||||
// Pretty print
|
// Pretty print
|
||||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
|
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
|
||||||
|
@ -608,13 +574,6 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
|
||||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(theResource);
|
|
||||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
|
||||||
addProfileToBundleEntry(theServer.getFhirContext(), theResource, serverBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String contentType;
|
String contentType;
|
||||||
if (theResource instanceof IBaseBinary && responseEncoding == null) {
|
if (theResource instanceof IBaseBinary && responseEncoding == null) {
|
||||||
IBaseBinary bin = (IBaseBinary) theResource;
|
IBaseBinary bin = (IBaseBinary) theResource;
|
||||||
|
|
|
@ -55,8 +55,6 @@ public interface IAnyResource extends IBaseResource {
|
||||||
|
|
||||||
IPrimitiveType<String> getLanguageElement();
|
IPrimitiveType<String> getLanguageElement();
|
||||||
|
|
||||||
IBaseMetaType getMeta();
|
|
||||||
|
|
||||||
public Object getUserData(String name);
|
public Object getUserData(String name);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,6 +39,8 @@ import ca.uhn.fhir.model.api.Include;
|
||||||
*/
|
*/
|
||||||
public interface IBaseResource extends IBase, IElement {
|
public interface IBaseResource extends IBase, IElement {
|
||||||
|
|
||||||
|
IBaseMetaType getMeta();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include constant for <code>*</code> (return all includes)
|
* Include constant for <code>*</code> (return all includes)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,7 +32,7 @@ package org.hl7.fhir.instance.model.api;
|
||||||
* which version of the strctures your application is using.
|
* which version of the strctures your application is using.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public interface IIdType extends IBase {
|
public interface IIdType extends IPrimitiveType<String> {
|
||||||
|
|
||||||
void applyTo(IBaseResource theResource);
|
void applyTo(IBaseResource theResource);
|
||||||
|
|
||||||
|
|
|
@ -36,5 +36,5 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package ca.uhn.fhir.model.dstu.resource;
|
package ca.uhn.fhir.model.dstu.resource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
|
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
|
||||||
|
@ -23,35 +28,31 @@ package ca.uhn.fhir.model.dstu.resource;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.BaseElement;
|
import ca.uhn.fhir.model.api.BaseElement;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
public abstract class BaseResource extends BaseElement implements IResource {
|
public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_language</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
|
|
||||||
public static final String SP_RES_LANGUAGE = "_language";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_id</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
|
|
||||||
public static final String SP_RES_ID = "_id";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
|
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -63,9 +64,24 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
|
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search parameter constant for <b>_id</b>
|
||||||
|
*/
|
||||||
|
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
|
||||||
|
public static final String SP_RES_ID = "_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search parameter constant for <b>_language</b>
|
||||||
|
*/
|
||||||
|
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
|
||||||
|
public static final String SP_RES_LANGUAGE = "_language";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Child(name = "contained", order = 2, min = 0, max = 1)
|
@Child(name = "contained", order = 2, min = 0, max = 1)
|
||||||
private ContainedDt myContained;
|
private ContainedDt myContained;
|
||||||
|
|
||||||
|
|
||||||
private IdDt myId;
|
private IdDt myId;
|
||||||
|
|
||||||
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
||||||
|
@ -104,6 +120,216 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return myLanguage;
|
return myLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType getMeta() {
|
||||||
|
return new IBaseMetaType() {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType addProfile(String theProfile) {
|
||||||
|
ArrayList<IdDt> newTagList = new ArrayList<IdDt>();
|
||||||
|
List<IdDt> existingTagList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
|
||||||
|
if (existingTagList != null) {
|
||||||
|
newTagList.addAll(existingTagList);
|
||||||
|
}
|
||||||
|
ResourceMetadataKeyEnum.PROFILES.put(BaseResource.this, newTagList);
|
||||||
|
|
||||||
|
IdDt tag = new IdDt(theProfile);
|
||||||
|
newTagList.add(tag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding addSecurity() {
|
||||||
|
List<BaseCodingDt> tagList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
|
||||||
|
if (tagList == null) {
|
||||||
|
tagList = new ArrayList<BaseCodingDt>();
|
||||||
|
ResourceMetadataKeyEnum.SECURITY_LABELS.put(BaseResource.this, tagList);
|
||||||
|
}
|
||||||
|
CodingDt tag = new CodingDt();
|
||||||
|
tagList.add(tag);
|
||||||
|
return asBaseCoding(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding addTag() {
|
||||||
|
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this);
|
||||||
|
if (tagList == null) {
|
||||||
|
tagList = new TagList();
|
||||||
|
ResourceMetadataKeyEnum.TAG_LIST.put(BaseResource.this, tagList);
|
||||||
|
}
|
||||||
|
Tag tag = new Tag();
|
||||||
|
tagList.add(tag);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This view is used because the old DSTU1 BaseCodingDt can't implements IBaseCoding
|
||||||
|
*/
|
||||||
|
private IBaseCoding asBaseCoding(final BaseCodingDt theCoding) {
|
||||||
|
return new IBaseCoding() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return theCoding.getCodeElement().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplay() {
|
||||||
|
return theCoding.getDisplayElement().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPost() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPre() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return theCoding.getSystemElement().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFormatComment() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return ElementUtil.isEmpty(getSystem(), getCode(), getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setCode(String theTerm) {
|
||||||
|
theCoding.setCode(theTerm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setDisplay(String theLabel) {
|
||||||
|
theCoding.setDisplay(theLabel);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding setSystem(String theScheme) {
|
||||||
|
theCoding.setSystem(theScheme);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPost() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPre() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getLastUpdated() {
|
||||||
|
InstantDt lu = ResourceMetadataKeyEnum.UPDATED.get(BaseResource.this);
|
||||||
|
if (lu != null) {
|
||||||
|
return lu.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IPrimitiveType<String>> getProfile() {
|
||||||
|
ArrayList<IPrimitiveType<String>> retVal = new ArrayList<IPrimitiveType<String>>();
|
||||||
|
List<IdDt> profilesList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
|
||||||
|
if (profilesList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
for (IdDt next : profilesList) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IBaseCoding> getSecurity() {
|
||||||
|
ArrayList<IBaseCoding> retVal = new ArrayList<IBaseCoding>();
|
||||||
|
List<BaseCodingDt> labelsList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
|
||||||
|
if (labelsList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
for (BaseCodingDt next : labelsList) {
|
||||||
|
retVal.add(asBaseCoding(next));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding getSecurity(String theSystem, String theCode) {
|
||||||
|
for (BaseCodingDt next : ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this)) {
|
||||||
|
if (theSystem.equals(next.getSystemElement().getValue()) && theCode.equals(next.getCodeElement().getValue())) {
|
||||||
|
return asBaseCoding(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IBaseCoding> getTag() {
|
||||||
|
ArrayList<IBaseCoding> retVal = new ArrayList<IBaseCoding>();
|
||||||
|
for (Tag next : ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this)) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding getTag(String theSystem, final String theCode) {
|
||||||
|
for (final Tag next : ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this)) {
|
||||||
|
if (next.getScheme().equals(theSystem) && next.getTerm().equals(theCode)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersionId() {
|
||||||
|
return getId().getVersionIdPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFormatComment() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return getResourceMetadata().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType setLastUpdated(Date theHeaderDateValue) {
|
||||||
|
ResourceMetadataKeyEnum.UPDATED.put(BaseResource.this, new InstantDt(theHeaderDateValue));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType setVersionId(String theVersionId) {
|
||||||
|
setId(getId().withVersion(theVersionId));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceMetadataMap getResourceMetadata() {
|
public ResourceMetadataMap getResourceMetadata() {
|
||||||
if (myResourceMetadata == null) {
|
if (myResourceMetadata == null) {
|
||||||
|
@ -120,10 +346,23 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return myText;
|
return myText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
|
||||||
|
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isBaseEmpty() {
|
||||||
|
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
|
||||||
|
}
|
||||||
|
|
||||||
public void setContained(ContainedDt theContained) {
|
public void setContained(ContainedDt theContained) {
|
||||||
myContained = theContained;
|
myContained = theContained;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(IdDt theId) {
|
||||||
|
myId = theId;
|
||||||
|
}
|
||||||
|
|
||||||
public BaseResource setId(IIdType theId) {
|
public BaseResource setId(IIdType theId) {
|
||||||
if (theId instanceof IdDt) {
|
if (theId instanceof IdDt) {
|
||||||
myId = (IdDt) theId;
|
myId = (IdDt) theId;
|
||||||
|
@ -133,10 +372,6 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(IdDt theId) {
|
|
||||||
myId = theId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseResource setId(String theId) {
|
public BaseResource setId(String theId) {
|
||||||
if (theId == null) {
|
if (theId == null) {
|
||||||
myId = null;
|
myId = null;
|
||||||
|
@ -168,13 +403,4 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
|
|
||||||
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isBaseEmpty() {
|
|
||||||
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ package ca.uhn.fhir.rest.server;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -29,7 +28,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -43,6 +41,8 @@ import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
@ -53,7 +53,6 @@ import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||||
|
|
||||||
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu1BundleFactory.class);
|
|
||||||
private Bundle myBundle;
|
private Bundle myBundle;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
|
|
||||||
|
@ -186,7 +185,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
public void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
||||||
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
||||||
int numToReturn;
|
int numToReturn;
|
||||||
String searchId = null;
|
String searchId = null;
|
||||||
|
@ -224,16 +223,11 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
|
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
||||||
|
addProfileIfNeeded(theServer, theServerBase, next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
|
||||||
for (IBaseResource nextRes : resourceList) {
|
|
||||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
|
||||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
|
||||||
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
||||||
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
||||||
|
@ -256,6 +250,23 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addProfileIfNeeded(IRestfulServer<?> theServer, String theServerBase, IBaseResource nextRes) {
|
||||||
|
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
||||||
|
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardType()) {
|
||||||
|
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) nextRes);
|
||||||
|
if (tl == null) {
|
||||||
|
tl = new TagList();
|
||||||
|
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) nextRes, tl);
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeResourceDefinition nextDef = myContext.getResourceDefinition(nextRes);
|
||||||
|
String profile = nextDef.getResourceProfile(theServerBase);
|
||||||
|
if (isNotBlank(profile)) {
|
||||||
|
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults,
|
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults,
|
||||||
BundleTypeEnum theBundleType) {
|
BundleTypeEnum theBundleType) {
|
||||||
|
|
|
@ -214,9 +214,6 @@ public class CustomTypeTest {
|
||||||
|
|
||||||
private static boolean ourReturnExtended = false;
|
private static boolean ourReturnExtended = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by dsotnikov on 2/25/2014.
|
|
||||||
*/
|
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
@Search
|
@Search
|
||||||
|
|
|
@ -7,6 +7,7 @@ import java.util.List;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -299,6 +300,12 @@ public class ServerInvalidDefinitionTest {
|
||||||
public List<String> getFormatCommentsPost() {
|
public List<String> getFormatCommentsPost() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType getMeta() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}.getClass();
|
}.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package ca.uhn.fhir.model.dstu2.resource;
|
package ca.uhn.fhir.model.dstu2.resource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR Structures - DSTU2 (FHIR v1.0.0)
|
* HAPI FHIR Structures - DSTU2 (FHIR v1.0.0)
|
||||||
|
@ -23,35 +28,31 @@ package ca.uhn.fhir.model.dstu2.resource;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.BaseElement;
|
import ca.uhn.fhir.model.api.BaseElement;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
|
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.NarrativeDt;
|
import ca.uhn.fhir.model.dstu2.composite.NarrativeDt;
|
||||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
public abstract class BaseResource extends BaseElement implements IResource {
|
public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_language</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
|
|
||||||
public static final String SP_RES_LANGUAGE = "_language";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_id</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
|
|
||||||
public static final String SP_RES_ID = "_id";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
|
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -62,10 +63,23 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
*/
|
*/
|
||||||
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
|
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search parameter constant for <b>_id</b>
|
||||||
|
*/
|
||||||
|
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
|
||||||
|
public static final String SP_RES_ID = "_id";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search parameter constant for <b>_language</b>
|
||||||
|
*/
|
||||||
|
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
|
||||||
|
public static final String SP_RES_LANGUAGE = "_language";
|
||||||
|
|
||||||
@Child(name = "contained", order = 2, min = 0, max = 1)
|
@Child(name = "contained", order = 2, min = 0, max = 1)
|
||||||
private ContainedDt myContained;
|
private ContainedDt myContained;
|
||||||
|
|
||||||
|
|
||||||
private IdDt myId;
|
private IdDt myId;
|
||||||
|
|
||||||
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
||||||
|
@ -104,6 +118,157 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return myLanguage;
|
return myLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType getMeta() {
|
||||||
|
return new IBaseMetaType() {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType addProfile(String theProfile) {
|
||||||
|
ArrayList<IdDt> newTagList = new ArrayList<IdDt>();
|
||||||
|
List<IdDt> existingTagList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
|
||||||
|
if (existingTagList != null) {
|
||||||
|
newTagList.addAll(existingTagList);
|
||||||
|
}
|
||||||
|
ResourceMetadataKeyEnum.PROFILES.put(BaseResource.this, newTagList);
|
||||||
|
|
||||||
|
IdDt tag = new IdDt(theProfile);
|
||||||
|
newTagList.add(tag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding addSecurity() {
|
||||||
|
List<BaseCodingDt> tagList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
|
||||||
|
if (tagList == null) {
|
||||||
|
tagList = new ArrayList<BaseCodingDt>();
|
||||||
|
ResourceMetadataKeyEnum.SECURITY_LABELS.put(BaseResource.this, tagList);
|
||||||
|
}
|
||||||
|
CodingDt tag = new CodingDt();
|
||||||
|
tagList.add(tag);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding addTag() {
|
||||||
|
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this);
|
||||||
|
if (tagList == null) {
|
||||||
|
tagList = new TagList();
|
||||||
|
ResourceMetadataKeyEnum.TAG_LIST.put(BaseResource.this, tagList);
|
||||||
|
}
|
||||||
|
Tag tag = new Tag();
|
||||||
|
tagList.add(tag);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPost() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFormatCommentsPre() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getLastUpdated() {
|
||||||
|
InstantDt lu = ResourceMetadataKeyEnum.UPDATED.get(BaseResource.this);
|
||||||
|
if (lu != null) {
|
||||||
|
return lu.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IPrimitiveType<String>> getProfile() {
|
||||||
|
ArrayList<IPrimitiveType<String>> retVal = new ArrayList<IPrimitiveType<String>>();
|
||||||
|
List<IdDt> profilesList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
|
||||||
|
if (profilesList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
for (IdDt next : profilesList) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IBaseCoding> getSecurity() {
|
||||||
|
ArrayList<CodingDt> retVal = new ArrayList<CodingDt>();
|
||||||
|
List<BaseCodingDt> labelsList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
|
||||||
|
if (labelsList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
for (BaseCodingDt next : labelsList) {
|
||||||
|
retVal.add(new CodingDt(next.getSystemElement().getValue(), next.getCodeElement().getValue()).setDisplay(next.getDisplayElement().getValue()));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding getSecurity(String theSystem, String theCode) {
|
||||||
|
for (IBaseCoding next : getSecurity()) {
|
||||||
|
if (theSystem.equals(next.getSystem()) && theCode.equals(next.getCode())) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IBaseCoding> getTag() {
|
||||||
|
ArrayList<IBaseCoding> retVal = new ArrayList<IBaseCoding>();
|
||||||
|
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this);
|
||||||
|
if (tagList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
for (Tag next : tagList) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseCoding getTag(String theSystem, String theCode) {
|
||||||
|
for (IBaseCoding next : getTag()) {
|
||||||
|
if (next.getSystem().equals(theSystem) && next.getCode().equals(theCode)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersionId() {
|
||||||
|
return getId().getVersionIdPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFormatComment() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return getResourceMetadata().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType setLastUpdated(Date theHeaderDateValue) {
|
||||||
|
ResourceMetadataKeyEnum.UPDATED.put(BaseResource.this, new InstantDt(theHeaderDateValue));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseMetaType setVersionId(String theVersionId) {
|
||||||
|
setId(getId().withVersion(theVersionId));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceMetadataMap getResourceMetadata() {
|
public ResourceMetadataMap getResourceMetadata() {
|
||||||
if (myResourceMetadata == null) {
|
if (myResourceMetadata == null) {
|
||||||
|
@ -120,6 +285,15 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return myText;
|
return myText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
|
||||||
|
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isBaseEmpty() {
|
||||||
|
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
|
||||||
|
}
|
||||||
|
|
||||||
public void setContained(ContainedDt theContained) {
|
public void setContained(ContainedDt theContained) {
|
||||||
myContained = theContained;
|
myContained = theContained;
|
||||||
}
|
}
|
||||||
|
@ -168,13 +342,4 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
|
|
||||||
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isBaseEmpty() {
|
|
||||||
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
@ -51,7 +50,6 @@ import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
@ -65,7 +63,6 @@ import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||||
|
|
||||||
public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu2BundleFactory.class);
|
|
||||||
private Bundle myBundle;
|
private Bundle myBundle;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private String myBase;
|
private String myBase;
|
||||||
|
@ -302,7 +299,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
public void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
||||||
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
||||||
myBase = theServerBase;
|
myBase = theServerBase;
|
||||||
|
|
||||||
|
@ -352,15 +349,6 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
|
||||||
for (IBaseResource nextRes : resourceList) {
|
|
||||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
|
||||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
|
||||||
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
||||||
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,510 @@
|
||||||
|
package ca.uhn.fhir.parser;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
|
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.dstu2.composite.QuantityDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||||
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
|
public class CustomTypeDstu2Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomTypeDstu2Test.class);
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forDstu2();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessEmptyMetaLists() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
assertThat(p.getMeta().getProfile(), empty());
|
||||||
|
assertThat(p.getMeta().getFormatCommentsPost(), empty());
|
||||||
|
assertThat(p.getMeta().getFormatCommentsPre(), empty());
|
||||||
|
assertThat(p.getMeta().getLastUpdated(), nullValue());
|
||||||
|
assertThat(p.getMeta().getSecurity(), empty());
|
||||||
|
assertThat(p.getMeta().getSecurity("foo", "bar"), nullValue());
|
||||||
|
assertThat(p.getMeta().getTag(), empty());
|
||||||
|
assertThat(p.getMeta().getTag("foo", "bar"), nullValue());
|
||||||
|
assertThat(p.getMeta().getVersionId(), nullValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeCompleteMetaLists() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.getMeta().addProfile("http://foo/profile1");
|
||||||
|
p.getMeta().addProfile("http://foo/profile2");
|
||||||
|
p.getMeta().addSecurity().setSystem("SEC_S1").setCode("SEC_C1").setDisplay("SED_D1");
|
||||||
|
p.getMeta().addSecurity().setSystem("SEC_S2").setCode("SEC_C2").setDisplay("SED_D2");
|
||||||
|
p.getMeta().addTag().setSystem("TAG_S1").setCode("TAG_C1").setDisplay("TAG_D1");
|
||||||
|
p.getMeta().addTag().setSystem("TAG_S2").setCode("TAG_C2").setDisplay("TAG_D2");
|
||||||
|
|
||||||
|
String out = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||||
|
ourLog.info(out);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(out, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://foo/profile1\"/>",
|
||||||
|
"<profile value=\"http://foo/profile2\"/>",
|
||||||
|
"<security>",
|
||||||
|
"<system value=\"SEC_S1\"/>",
|
||||||
|
"<code value=\"SEC_C1\"/>",
|
||||||
|
"<display value=\"SED_D1\"/>",
|
||||||
|
"</security>",
|
||||||
|
"<security>",
|
||||||
|
"<system value=\"SEC_S2\"/>",
|
||||||
|
"<code value=\"SEC_C2\"/>",
|
||||||
|
"<display value=\"SED_D2\"/>",
|
||||||
|
"</security>",
|
||||||
|
"<tag>",
|
||||||
|
"<system value=\"TAG_S1\"/>",
|
||||||
|
"<display value=\"TAG_D1\"/>",
|
||||||
|
"</tag>",
|
||||||
|
"<tag>",
|
||||||
|
"<system value=\"TAG_S2\"/>",
|
||||||
|
"<display value=\"TAG_D2\"/>",
|
||||||
|
"</tag>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeWithCustomType() {
|
||||||
|
|
||||||
|
MyCustomPatient patient = new MyCustomPatient();
|
||||||
|
|
||||||
|
patient.addIdentifier().setSystem("urn:system").setValue("1234");
|
||||||
|
patient.addName().addFamily("Rossi").addGiven("Mario");
|
||||||
|
patient.setInsulinLevel(new QuantityDt());
|
||||||
|
patient.setGlucoseLevel(new QuantityDt());
|
||||||
|
patient.setHbA1c(new QuantityDt());
|
||||||
|
patient.setBloodPressure(new QuantityDt());
|
||||||
|
patient.setCholesterol(new QuantityDt());
|
||||||
|
patient.setWeight(new StringDt("80 kg"));
|
||||||
|
patient.setWeight(new StringDt("185 cm"));
|
||||||
|
patient.setCheckDates(new ArrayList<DateTimeDt>());
|
||||||
|
patient.getCheckDates().add(new DateTimeDt("2014-01-26T11:11:11"));
|
||||||
|
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
String messageString = p.encodeResourceToString(patient);
|
||||||
|
|
||||||
|
ourLog.info(messageString);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, not(stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"", "/>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>")));
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeWithCustomTypeAndAutoInsertedProfile() {
|
||||||
|
|
||||||
|
MyCustomPatient patient = new MyCustomPatient();
|
||||||
|
|
||||||
|
patient.getMeta().addProfile("http://example.com/foo");
|
||||||
|
patient.getMeta().addProfile("http://example.com/bar");
|
||||||
|
|
||||||
|
patient.addIdentifier().setSystem("urn:system").setValue("1234");
|
||||||
|
patient.addName().addFamily("Rossi").addGiven("Mario");
|
||||||
|
patient.setInsulinLevel(new QuantityDt());
|
||||||
|
patient.setGlucoseLevel(new QuantityDt());
|
||||||
|
patient.setHbA1c(new QuantityDt());
|
||||||
|
patient.setBloodPressure(new QuantityDt());
|
||||||
|
patient.setCholesterol(new QuantityDt());
|
||||||
|
patient.setWeight(new StringDt("80 kg"));
|
||||||
|
patient.setWeight(new StringDt("185 cm"));
|
||||||
|
patient.setCheckDates(new ArrayList<DateTimeDt>());
|
||||||
|
patient.getCheckDates().add(new DateTimeDt("2014-01-26T11:11:11"));
|
||||||
|
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
String messageString = p.encodeResourceToString(patient);
|
||||||
|
|
||||||
|
ourLog.info(messageString);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"<profile value=\"http://example.com/bar\"/>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, not(stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"", "/>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>")));
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeNormalType() {
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
|
||||||
|
patient.addIdentifier().setSystem("urn:system").setValue("1234");
|
||||||
|
patient.addName().addFamily("Rossi").addGiven("Mario");
|
||||||
|
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
String messageString = p.encodeResourceToString(patient);
|
||||||
|
ourLog.info(messageString);
|
||||||
|
|
||||||
|
assertThat(messageString, not(containsString("<profile")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseResourceWithNoDirective() {
|
||||||
|
String input = createResource(true);
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
|
Patient parsed = (Patient) ctx.newXmlParser().parseResource(input);
|
||||||
|
assertEquals(1, parsed.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", parsed.getMeta().getProfile().get(0).getValue());
|
||||||
|
|
||||||
|
List<ExtensionDt> exts = parsed.getUndeclaredExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(1, exts.size());
|
||||||
|
assertEquals("185 cm", ((StringDt)exts.get(0).getValueAsPrimitive()).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseResourceWithDirective() {
|
||||||
|
String input = createResource(true);
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
|
ctx.setDefaultTypeForProfile("http://example.com/foo", MyCustomPatient.class);
|
||||||
|
|
||||||
|
MyCustomPatient parsed = (MyCustomPatient) ctx.newXmlParser().parseResource(input);
|
||||||
|
assertEquals(1, parsed.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", parsed.getMeta().getProfile().get(0).getValue());
|
||||||
|
|
||||||
|
List<ExtensionDt> exts = parsed.getUndeclaredExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(0, exts.size());
|
||||||
|
|
||||||
|
assertEquals("185 cm", parsed.getWeight().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseBundleWithResourceDirective() {
|
||||||
|
|
||||||
|
String input = createBundle(createResource(false), createResource(true));
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
|
ctx.setDefaultTypeForProfile("http://example.com/foo", MyCustomPatient.class);
|
||||||
|
|
||||||
|
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
|
||||||
|
Patient res0 = (Patient) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(0, res0.getMeta().getProfile().size());
|
||||||
|
List<ExtensionDt> exts = res0.getUndeclaredExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(1, exts.size());
|
||||||
|
assertEquals("185 cm", ((StringDt)exts.get(0).getValueAsPrimitive()).getValue());
|
||||||
|
|
||||||
|
MyCustomPatient res1 = (MyCustomPatient) bundle.getEntry().get(1).getResource();
|
||||||
|
assertEquals(1, res1.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", res1.getMeta().getProfile().get(0).getValue());
|
||||||
|
exts = res1.getUndeclaredExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(0, exts.size());
|
||||||
|
assertEquals("185 cm", res1.getWeight().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createBundle(String... theResources) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("<Bundle xmlns=\"http://hl7.org/fhir\">\n");
|
||||||
|
for (String next : theResources) {
|
||||||
|
b.append(" <entry>\n");
|
||||||
|
b.append(" <resource>\n");
|
||||||
|
b.append(next);
|
||||||
|
b.append(" </resource>\n");
|
||||||
|
b.append(" </entry>\n");
|
||||||
|
}
|
||||||
|
b.append("</Bundle>");
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createResource(boolean theWithProfile) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("<Patient xmlns=\"http://hl7.org/fhir\">\n");
|
||||||
|
if (theWithProfile) {
|
||||||
|
b.append(" <meta>\n");
|
||||||
|
b.append(" <profile value=\"http://example.com/foo\"/>\n");
|
||||||
|
b.append(" </meta>\n");
|
||||||
|
}
|
||||||
|
b.append(" <extension url=\"http://example.com/BloodPressure\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"110\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmHg\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <modifierExtension url=\"http://example.com/diabetes2\">\n");
|
||||||
|
b.append(" <valueDateTime value=\"2010-01-02\"/>\n");
|
||||||
|
b.append(" </modifierExtension>\n");
|
||||||
|
b.append(" <modifierExtension url=\"http://example.com/diabetes2\">\n");
|
||||||
|
b.append(" <valueDateTime value=\"2014-01-26T11:11:11\"/>\n");
|
||||||
|
b.append(" </modifierExtension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Cholesterol\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"2\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmol/l\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Glucose\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"95\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mg/dl\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/HbA1c\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"48\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmol/mol\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Insuline\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"125\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"pmol/l\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Weight\">\n");
|
||||||
|
b.append(" <valueString value=\"185 cm\"/>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <identifier>\n");
|
||||||
|
b.append(" <system value=\"urn:system\"/>\n");
|
||||||
|
b.append(" <value value=\"1234\"/>\n");
|
||||||
|
b.append(" </identifier>\n");
|
||||||
|
b.append(" <name>\n");
|
||||||
|
b.append(" <family value=\"Rossi\"/>\n");
|
||||||
|
b.append(" <given value=\"Mario\"/>\n");
|
||||||
|
b.append(" </name>\n");
|
||||||
|
b.append("</Patient>");
|
||||||
|
String input =
|
||||||
|
b.toString();
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ResourceDef(name = "Patient", profile = "http://example.com/foo")
|
||||||
|
public static class MyCustomPatient extends Patient {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Child(name = "bloodPressure") // once every 3 month. The average target is 130/80 mmHg or less
|
||||||
|
@Extension(url = "http://example.com/BloodPressure", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The value of the patient's blood pressure")
|
||||||
|
private QuantityDt myBloodPressure;
|
||||||
|
|
||||||
|
// Dates of periodic tests
|
||||||
|
@Child(name = "CheckDates", max = Child.MAX_UNLIMITED)
|
||||||
|
@Extension(url = "http://example.com/diabetes2", definedLocally = false, isModifier = true)
|
||||||
|
@Description(shortDefinition = "Dates of periodic tests")
|
||||||
|
private List<DateTimeDt> myCheckDates;
|
||||||
|
|
||||||
|
@Child(name = "cholesterol") // once a year. The target is triglycerides =< 2 mmol/l e cholesterol =< 4 mmol/l
|
||||||
|
@Extension(url = "http://example.com/Cholesterol", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The value of the patient's cholesterol")
|
||||||
|
private QuantityDt myCholesterol;
|
||||||
|
|
||||||
|
@Child(name = "glucoseLevel") // fingerprick test
|
||||||
|
@Extension(url = "http://example.com/Glucose", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The value of the patient's blood glucose")
|
||||||
|
private QuantityDt myGlucoseLevel;
|
||||||
|
|
||||||
|
// Periodic Tests
|
||||||
|
@Child(name = "hbA1c") // once every 6 month. The average target is 53 mmol/mol (or 7%) or less.
|
||||||
|
@Extension(url = "http://example.com/HbA1c", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The value of the patient's glucose")
|
||||||
|
private QuantityDt myHbA1c;
|
||||||
|
|
||||||
|
@Child(name = "Height")
|
||||||
|
@Extension(url = "http://example.com/Height", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The patient's height in cm")
|
||||||
|
private StringDt myHeight;
|
||||||
|
|
||||||
|
@Child(name = "insulinLevel") // Normal range is [43,208] pmol/l
|
||||||
|
@Extension(url = "http://example.com/Insuline", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The value of the patient's insulin")
|
||||||
|
private QuantityDt myInsulinLevel;
|
||||||
|
|
||||||
|
// Other parameters
|
||||||
|
@Child(name = "weight")
|
||||||
|
@Extension(url = "http://example.com/Weight", definedLocally = false, isModifier = false)
|
||||||
|
@Description(shortDefinition = "The patient's weight in Kg")
|
||||||
|
private StringDt myWeight;
|
||||||
|
|
||||||
|
public QuantityDt Cholesterol() {
|
||||||
|
if (myCholesterol == null) {
|
||||||
|
myCholesterol = new QuantityDt();
|
||||||
|
}
|
||||||
|
myCholesterol.getValue();
|
||||||
|
myCholesterol.getSystem();
|
||||||
|
myCholesterol.getCode();
|
||||||
|
|
||||||
|
return myCholesterol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuantityDt getBloodPressure() {
|
||||||
|
if (myBloodPressure == null) {
|
||||||
|
myBloodPressure = new QuantityDt();
|
||||||
|
}
|
||||||
|
myBloodPressure.getValue();
|
||||||
|
myBloodPressure.getSystem();
|
||||||
|
myBloodPressure.getCode();
|
||||||
|
|
||||||
|
return myBloodPressure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DateTimeDt> getCheckDates() {
|
||||||
|
if (myCheckDates == null) {
|
||||||
|
myCheckDates = new ArrayList<DateTimeDt>();
|
||||||
|
}
|
||||||
|
return myCheckDates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuantityDt getGlucoseLevel() {
|
||||||
|
if (myGlucoseLevel == null) {
|
||||||
|
myGlucoseLevel = new QuantityDt();
|
||||||
|
}
|
||||||
|
myGlucoseLevel.getValue();
|
||||||
|
myGlucoseLevel.getSystem();
|
||||||
|
myGlucoseLevel.getCode();
|
||||||
|
|
||||||
|
return myGlucoseLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuantityDt getHbA1c() {
|
||||||
|
if (myHbA1c == null) {
|
||||||
|
myHbA1c = new QuantityDt();
|
||||||
|
}
|
||||||
|
myHbA1c.getValue();
|
||||||
|
myHbA1c.getSystem();
|
||||||
|
myHbA1c.getCode();
|
||||||
|
|
||||||
|
return myHbA1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringDt getHeight() {
|
||||||
|
if (myHeight == null) {
|
||||||
|
myHeight = new StringDt();
|
||||||
|
}
|
||||||
|
return myHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuantityDt getInsulinLevel() {
|
||||||
|
if (myInsulinLevel == null) {
|
||||||
|
myInsulinLevel = new QuantityDt();
|
||||||
|
}
|
||||||
|
myInsulinLevel.getValue();
|
||||||
|
myInsulinLevel.getSystem();
|
||||||
|
myInsulinLevel.getCode();
|
||||||
|
|
||||||
|
return myInsulinLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringDt getWeight() {
|
||||||
|
if (myWeight == null) {
|
||||||
|
myWeight = new StringDt();
|
||||||
|
}
|
||||||
|
return myWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return super.isEmpty() && ElementUtil.isEmpty(myInsulinLevel, myGlucoseLevel, myHbA1c, myBloodPressure, myCholesterol, myWeight, myHeight, myCheckDates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBloodPressure(QuantityDt bloodPressure) {
|
||||||
|
myBloodPressure = bloodPressure;
|
||||||
|
myBloodPressure.setValue(110);
|
||||||
|
myBloodPressure.setSystem("http://unitsofmeasure.org");
|
||||||
|
myBloodPressure.setCode("mmHg");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckDates(List<DateTimeDt> theCheckDates) {
|
||||||
|
myCheckDates = theCheckDates;
|
||||||
|
myCheckDates.add(new DateTimeDt("2010-01-02"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCholesterol(QuantityDt cholesterol) {
|
||||||
|
myCholesterol = cholesterol;
|
||||||
|
myCholesterol.setValue(2);
|
||||||
|
myCholesterol.setSystem("http://unitsofmeasure.org");
|
||||||
|
myCholesterol.setCode("mmol/l");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGlucoseLevel(QuantityDt glucoseLevel) {
|
||||||
|
myGlucoseLevel = glucoseLevel;
|
||||||
|
myGlucoseLevel.setValue(95);
|
||||||
|
myGlucoseLevel.setSystem("http://unitsofmeasure.org");
|
||||||
|
myGlucoseLevel.setCode("mg/dl");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHbA1c(QuantityDt hba1c) {
|
||||||
|
myHbA1c = hba1c;
|
||||||
|
myHbA1c.setValue(48);
|
||||||
|
myHbA1c.setSystem("http://unitsofmeasure.org");
|
||||||
|
myHbA1c.setCode("mmol/mol");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(StringDt height) {
|
||||||
|
myHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setter/Getter methods
|
||||||
|
public void setInsulinLevel(QuantityDt insulinLevel) {
|
||||||
|
myInsulinLevel = insulinLevel;
|
||||||
|
myInsulinLevel.setValue(125);
|
||||||
|
myInsulinLevel.setSystem("http://unitsofmeasure.org");
|
||||||
|
myInsulinLevel.setCode("pmol/l");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeight(StringDt weight) {
|
||||||
|
myWeight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,228 +0,0 @@
|
||||||
package ca.uhn.fhir.parser;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
|
||||||
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.dstu2.composite.QuantityDt;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|
||||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
|
||||||
|
|
||||||
public class CustomTypeTest {
|
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomTypeTest.class);
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncode() {
|
|
||||||
|
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
|
||||||
|
|
||||||
MyCustomPatient patient = new MyCustomPatient();
|
|
||||||
|
|
||||||
patient.addIdentifier().setSystem("urn:system").setValue("1234");
|
|
||||||
patient.addName().addFamily("Rossi").addGiven("Mario");
|
|
||||||
patient.setInsulinLevel(new QuantityDt());
|
|
||||||
patient.setGlucoseLevel(new QuantityDt());
|
|
||||||
patient.setHbA1c(new QuantityDt());
|
|
||||||
patient.setBloodPressure(new QuantityDt());
|
|
||||||
patient.setCholesterol(new QuantityDt());
|
|
||||||
patient.setWeight(new StringDt("80 kg"));
|
|
||||||
patient.setWeight(new StringDt("185 cm"));
|
|
||||||
patient.setCheckDates(new ArrayList<DateTimeDt>());
|
|
||||||
patient.getCheckDates().add(new DateTimeDt("2014-01-26T11:11:11"));
|
|
||||||
|
|
||||||
IParser p = ctx.newXmlParser().setPrettyPrint(true);
|
|
||||||
String messageString = p.encodeResourceToString(patient);
|
|
||||||
|
|
||||||
ourLog.info(messageString);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResourceDef(name = "Patient")
|
|
||||||
public static class MyCustomPatient extends Patient {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Child(name = "bloodPressure") // once every 3 month. The average target is 130/80 mmHg or less
|
|
||||||
@Extension(url = "http://example.com/BloodPressure", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The value of the patient's blood pressure")
|
|
||||||
private QuantityDt myBloodPressure;
|
|
||||||
|
|
||||||
// Dates of periodic tests
|
|
||||||
@Child(name = "CheckDates", max = Child.MAX_UNLIMITED)
|
|
||||||
@Extension(url = "http://example.com/diabetes2", definedLocally = false, isModifier = true)
|
|
||||||
@Description(shortDefinition = "Dates of periodic tests")
|
|
||||||
private List<DateTimeDt> myCheckDates;
|
|
||||||
|
|
||||||
@Child(name = "cholesterol") // once a year. The target is triglycerides =< 2 mmol/l e cholesterol =< 4 mmol/l
|
|
||||||
@Extension(url = "http://example.com/Cholesterol", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The value of the patient's cholesterol")
|
|
||||||
private QuantityDt myCholesterol;
|
|
||||||
|
|
||||||
@Child(name = "glucoseLevel") // fingerprick test
|
|
||||||
@Extension(url = "http://example.com/Glucose", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The value of the patient's blood glucose")
|
|
||||||
private QuantityDt myGlucoseLevel;
|
|
||||||
|
|
||||||
// Periodic Tests
|
|
||||||
@Child(name = "hbA1c") // once every 6 month. The average target is 53 mmol/mol (or 7%) or less.
|
|
||||||
@Extension(url = "http://example.com/HbA1c", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The value of the patient's glucose")
|
|
||||||
private QuantityDt myHbA1c;
|
|
||||||
|
|
||||||
@Child(name = "Height")
|
|
||||||
@Extension(url = "http://example.com/Height", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The patient's height in cm")
|
|
||||||
private StringDt myHeight;
|
|
||||||
|
|
||||||
@Child(name = "insulinLevel") // Normal range is [43,208] pmol/l
|
|
||||||
@Extension(url = "http://example.com/Insuline", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The value of the patient's insulin")
|
|
||||||
private QuantityDt myInsulinLevel;
|
|
||||||
|
|
||||||
// Other parameters
|
|
||||||
@Child(name = "weight")
|
|
||||||
@Extension(url = "http://example.com/Weight", definedLocally = false, isModifier = false)
|
|
||||||
@Description(shortDefinition = "The patient's weight in Kg")
|
|
||||||
private StringDt myWeight;
|
|
||||||
|
|
||||||
public QuantityDt Cholesterol() {
|
|
||||||
if (myCholesterol == null) {
|
|
||||||
myCholesterol = new QuantityDt();
|
|
||||||
}
|
|
||||||
myCholesterol.getValue();
|
|
||||||
myCholesterol.getSystem();
|
|
||||||
myCholesterol.getCode();
|
|
||||||
|
|
||||||
return myCholesterol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QuantityDt getBloodPressure() {
|
|
||||||
if (myBloodPressure == null) {
|
|
||||||
myBloodPressure = new QuantityDt();
|
|
||||||
}
|
|
||||||
myBloodPressure.getValue();
|
|
||||||
myBloodPressure.getSystem();
|
|
||||||
myBloodPressure.getCode();
|
|
||||||
|
|
||||||
return myBloodPressure;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DateTimeDt> getCheckDates() {
|
|
||||||
if (myCheckDates == null) {
|
|
||||||
myCheckDates = new ArrayList<DateTimeDt>();
|
|
||||||
}
|
|
||||||
return myCheckDates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QuantityDt getGlucoseLevel() {
|
|
||||||
if (myGlucoseLevel == null) {
|
|
||||||
myGlucoseLevel = new QuantityDt();
|
|
||||||
}
|
|
||||||
myGlucoseLevel.getValue();
|
|
||||||
myGlucoseLevel.getSystem();
|
|
||||||
myGlucoseLevel.getCode();
|
|
||||||
|
|
||||||
return myGlucoseLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QuantityDt getHbA1c() {
|
|
||||||
if (myHbA1c == null) {
|
|
||||||
myHbA1c = new QuantityDt();
|
|
||||||
}
|
|
||||||
myHbA1c.getValue();
|
|
||||||
myHbA1c.getSystem();
|
|
||||||
myHbA1c.getCode();
|
|
||||||
|
|
||||||
return myHbA1c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringDt getHeight() {
|
|
||||||
if (myHeight == null) {
|
|
||||||
myHeight = new StringDt();
|
|
||||||
}
|
|
||||||
return myHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QuantityDt getInsulinLevel() {
|
|
||||||
if (myInsulinLevel == null) {
|
|
||||||
myInsulinLevel = new QuantityDt();
|
|
||||||
}
|
|
||||||
myInsulinLevel.getValue();
|
|
||||||
myInsulinLevel.getSystem();
|
|
||||||
myInsulinLevel.getCode();
|
|
||||||
|
|
||||||
return myInsulinLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringDt getWeight() {
|
|
||||||
if (myWeight == null) {
|
|
||||||
myWeight = new StringDt();
|
|
||||||
}
|
|
||||||
return myWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return super.isEmpty() && ElementUtil.isEmpty(myInsulinLevel, myGlucoseLevel, myHbA1c, myBloodPressure, myCholesterol, myWeight, myHeight, myCheckDates);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBloodPressure(QuantityDt bloodPressure) {
|
|
||||||
myBloodPressure = bloodPressure;
|
|
||||||
myBloodPressure.setValue(110);
|
|
||||||
myBloodPressure.setSystem("http://unitsofmeasure.org");
|
|
||||||
myBloodPressure.setCode("mmHg");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckDates(List<DateTimeDt> theCheckDates) {
|
|
||||||
myCheckDates = theCheckDates;
|
|
||||||
myCheckDates.add(new DateTimeDt("2010-01-02"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCholesterol(QuantityDt cholesterol) {
|
|
||||||
myCholesterol = cholesterol;
|
|
||||||
myCholesterol.setValue(2);
|
|
||||||
myCholesterol.setSystem("http://unitsofmeasure.org");
|
|
||||||
myCholesterol.setCode("mmol/l");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlucoseLevel(QuantityDt glucoseLevel) {
|
|
||||||
myGlucoseLevel = glucoseLevel;
|
|
||||||
myGlucoseLevel.setValue(95);
|
|
||||||
myGlucoseLevel.setSystem("http://unitsofmeasure.org");
|
|
||||||
myGlucoseLevel.setCode("mg/dl");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHbA1c(QuantityDt hba1c) {
|
|
||||||
myHbA1c = hba1c;
|
|
||||||
myHbA1c.setValue(48);
|
|
||||||
myHbA1c.setSystem("http://unitsofmeasure.org");
|
|
||||||
myHbA1c.setCode("mmol/mol");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeight(StringDt height) {
|
|
||||||
myHeight = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setter/Getter methods
|
|
||||||
public void setInsulinLevel(QuantityDt insulinLevel) {
|
|
||||||
myInsulinLevel = insulinLevel;
|
|
||||||
myInsulinLevel.setValue(125);
|
|
||||||
myInsulinLevel.setSystem("http://unitsofmeasure.org");
|
|
||||||
myInsulinLevel.setCode("pmol/l");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWeight(StringDt weight) {
|
|
||||||
myWeight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -94,6 +94,24 @@ public class JsonParserDstu2Test {
|
||||||
assertEquals(true, obs.getReadOnly().getValue().booleanValue());
|
assertEquals(true, obs.getReadOnly().getValue().booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseBundleWithCustomObservationType() {
|
||||||
|
ReportObservation obs = new ReportObservation();
|
||||||
|
obs.setReadOnly(true);
|
||||||
|
|
||||||
|
IParser p = ourCtx.newJsonParser();
|
||||||
|
// p.set
|
||||||
|
p.setParserErrorHandler(mock(IParserErrorHandler.class, new ThrowsException(new IllegalStateException())));
|
||||||
|
|
||||||
|
String encoded = p.encodeResourceToString(obs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
obs = p.parseResource(ReportObservation.class, encoded);
|
||||||
|
assertEquals(true, obs.getReadOnly().getValue().booleanValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseExtensions() throws Exception {
|
public void testEncodeAndParseExtensions() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
@ResourceDef(name = "Observation", id = "reportobservation")
|
@ResourceDef(name = "Observation", id = "http://example.com/reportobservation")
|
||||||
public class ReportObservation extends Observation {
|
public class ReportObservation extends Observation {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<Bundle
|
<Bundle xmlns="http://hl7.org/fhir">
|
||||||
xmlns="http://hl7.org/fhir">
|
|
||||||
<id value="487d3669-0e1c-4867-b124-400d1849548d"></id>
|
<id value="487d3669-0e1c-4867-b124-400d1849548d"></id>
|
||||||
<type value="searchset"></type>
|
<type value="searchset"></type>
|
||||||
<base value="http://localhost:19080/fhir/dstu1"></base>
|
<base value="http://localhost:19080/fhir/dstu1"></base>
|
||||||
|
@ -17,8 +16,7 @@
|
||||||
<url value="Observation"></url>
|
<url value="Observation"></url>
|
||||||
</link>
|
</link>
|
||||||
<resource>
|
<resource>
|
||||||
<Observation
|
<Observation xmlns="http://hl7.org/fhir">
|
||||||
xmlns="http://hl7.org/fhir">
|
|
||||||
<id value="0d87f02c-da2c-4551-9ead-2956f0165a4f"></id>
|
<id value="0d87f02c-da2c-4551-9ead-2956f0165a4f"></id>
|
||||||
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||||
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||||
|
@ -46,8 +44,7 @@
|
||||||
<url value="Observation"></url>
|
<url value="Observation"></url>
|
||||||
</link>
|
</link>
|
||||||
<resource>
|
<resource>
|
||||||
<Observation
|
<Observation xmlns="http://hl7.org/fhir">
|
||||||
xmlns="http://hl7.org/fhir">
|
|
||||||
<id value="c54ac0cc-a99f-40aa-9541-c5aa853a2e88"></id>
|
<id value="c54ac0cc-a99f-40aa-9541-c5aa853a2e88"></id>
|
||||||
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||||
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||||
|
|
|
@ -31,27 +31,24 @@ import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.DomainResource;
|
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
|
||||||
import org.hl7.fhir.dstu3.model.Resource;
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleLinkComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleLinkComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode;
|
import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode;
|
||||||
|
import org.hl7.fhir.dstu3.model.DomainResource;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Resource;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
@ -65,7 +62,6 @@ import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||||
|
|
||||||
public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
|
public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu3BundleFactory.class);
|
|
||||||
private Bundle myBundle;
|
private Bundle myBundle;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private String myBase;
|
private String myBase;
|
||||||
|
@ -308,7 +304,7 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
public void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
||||||
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
||||||
myBase = theServerBase;
|
myBase = theServerBase;
|
||||||
|
|
||||||
|
@ -358,15 +354,6 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
|
||||||
for (IBaseResource nextRes : resourceList) {
|
|
||||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
|
||||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
|
||||||
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
||||||
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,24 @@ import org.junit.Test;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeChildDatatypeDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeChildDatatypeDefinition;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
||||||
|
|
||||||
public class FhirContextDstu3Test {
|
public class FhirContextDstu3Test {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContextDstu3Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContextDstu3Test.class);
|
||||||
|
|
||||||
private FhirContext ourCtx = FhirContext.forDstu3();
|
private FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustomTypeDoesntBecomeDefault() {
|
||||||
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
|
||||||
|
MyPatientWithExtensions pt = new MyPatientWithExtensions();
|
||||||
|
pt.addName().addGiven("FOO");
|
||||||
|
ctx.newXmlParser().encodeResourceToString(pt);
|
||||||
|
|
||||||
|
assertEquals(Patient.class, ctx.getResourceDefinition("Patient").getImplementingClass());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQueryBoundCode() {
|
public void testQueryBoundCode() {
|
||||||
RuntimeResourceDefinition patientType = ourCtx.getResourceDefinition(Patient.class);
|
RuntimeResourceDefinition patientType = ourCtx.getResourceDefinition(Patient.class);
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
package ca.uhn.fhir.parser;
|
package ca.uhn.fhir.parser;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.model.DateTimeType;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity;
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
@ -13,17 +22,215 @@ import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
|
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
|
||||||
public class CustomTypeDstu3Test {
|
public class CustomTypeDstu3Test {
|
||||||
|
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomTypeDstu3Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomTypeDstu3Test.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String createBundle(String... theResources) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("<Bundle xmlns=\"http://hl7.org/fhir\">\n");
|
||||||
|
for (String next : theResources) {
|
||||||
|
b.append(" <entry>\n");
|
||||||
|
b.append(" <resource>\n");
|
||||||
|
b.append(next);
|
||||||
|
b.append(" </resource>\n");
|
||||||
|
b.append(" </entry>\n");
|
||||||
|
}
|
||||||
|
b.append("</Bundle>");
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createResource(boolean theWithProfile) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("<Patient xmlns=\"http://hl7.org/fhir\">\n");
|
||||||
|
if (theWithProfile) {
|
||||||
|
b.append(" <meta>\n");
|
||||||
|
b.append(" <profile value=\"http://example.com/foo\"/>\n");
|
||||||
|
b.append(" </meta>\n");
|
||||||
|
}
|
||||||
|
b.append(" <extension url=\"http://example.com/BloodPressure\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"110\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmHg\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <modifierExtension url=\"http://example.com/diabetes2\">\n");
|
||||||
|
b.append(" <valueDateTime value=\"2010-01-02\"/>\n");
|
||||||
|
b.append(" </modifierExtension>\n");
|
||||||
|
b.append(" <modifierExtension url=\"http://example.com/diabetes2\">\n");
|
||||||
|
b.append(" <valueDateTime value=\"2014-01-26T11:11:11\"/>\n");
|
||||||
|
b.append(" </modifierExtension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Cholesterol\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"2\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmol/l\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Glucose\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"95\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mg/dl\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/HbA1c\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"48\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"mmol/mol\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Insuline\">\n");
|
||||||
|
b.append(" <valueQuantity>\n");
|
||||||
|
b.append(" <value value=\"125\"/>\n");
|
||||||
|
b.append(" <system value=\"http://unitsofmeasure.org\"/>\n");
|
||||||
|
b.append(" <code value=\"pmol/l\"/>\n");
|
||||||
|
b.append(" </valueQuantity>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <extension url=\"http://example.com/Weight\">\n");
|
||||||
|
b.append(" <valueString value=\"185 cm\"/>\n");
|
||||||
|
b.append(" </extension>\n");
|
||||||
|
b.append(" <identifier>\n");
|
||||||
|
b.append(" <system value=\"urn:system\"/>\n");
|
||||||
|
b.append(" <value value=\"1234\"/>\n");
|
||||||
|
b.append(" </identifier>\n");
|
||||||
|
b.append(" <name>\n");
|
||||||
|
b.append(" <family value=\"Rossi\"/>\n");
|
||||||
|
b.append(" <given value=\"Mario\"/>\n");
|
||||||
|
b.append(" </name>\n");
|
||||||
|
b.append("</Patient>");
|
||||||
|
String input =
|
||||||
|
b.toString();
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncode() {
|
public void parseBundleWithResourceDirective() {
|
||||||
|
|
||||||
|
String input = createBundle(createResource(false), createResource(true));
|
||||||
|
|
||||||
FhirContext ctx = FhirContext.forDstu3();
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
ctx.setDefaultTypeForProfile("http://example.com/foo", MyCustomPatient.class);
|
||||||
|
|
||||||
|
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
|
||||||
|
Patient res0 = (Patient) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(0, res0.getMeta().getProfile().size());
|
||||||
|
List<org.hl7.fhir.dstu3.model.Extension> exts = res0.getExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(1, exts.size());
|
||||||
|
assertEquals("185 cm", ((StringType)exts.get(0).getValue()).getValue());
|
||||||
|
|
||||||
|
MyCustomPatient res1 = (MyCustomPatient) bundle.getEntry().get(1).getResource();
|
||||||
|
assertEquals(1, res1.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", res1.getMeta().getProfile().get(0).getValue());
|
||||||
|
exts = res1.getExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(0, exts.size());
|
||||||
|
assertEquals("185 cm", res1.getWeight().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseResourceWithDirective() {
|
||||||
|
String input = createResource(true);
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
ctx.setDefaultTypeForProfile("http://example.com/foo", MyCustomPatient.class);
|
||||||
|
|
||||||
|
MyCustomPatient parsed = (MyCustomPatient) ctx.newXmlParser().parseResource(input);
|
||||||
|
assertEquals(1, parsed.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", parsed.getMeta().getProfile().get(0).getValue());
|
||||||
|
|
||||||
|
List<org.hl7.fhir.dstu3.model.Extension> exts = parsed.getExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(0, exts.size());
|
||||||
|
|
||||||
|
assertEquals("185 cm", parsed.getWeight().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseResourceWithNoDirective() {
|
||||||
|
String input = createResource(true);
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
Patient parsed = (Patient) ctx.newXmlParser().parseResource(input);
|
||||||
|
assertEquals(1, parsed.getMeta().getProfile().size());
|
||||||
|
assertEquals("http://example.com/foo", parsed.getMeta().getProfile().get(0).getValue());
|
||||||
|
|
||||||
|
List<org.hl7.fhir.dstu3.model.Extension> exts = parsed.getExtensionsByUrl("http://example.com/Weight");
|
||||||
|
assertEquals(1, exts.size());
|
||||||
|
assertEquals("185 cm", ((StringType)exts.get(0).getValue()).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessEmptyMetaLists() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
assertThat(p.getMeta().getProfile(), empty());
|
||||||
|
assertThat(p.getMeta().getFormatCommentsPost(), empty());
|
||||||
|
assertThat(p.getMeta().getFormatCommentsPre(), empty());
|
||||||
|
assertThat(p.getMeta().getLastUpdated(), nullValue());
|
||||||
|
assertThat(p.getMeta().getSecurity(), empty());
|
||||||
|
assertThat(p.getMeta().getSecurity("foo", "bar"), nullValue());
|
||||||
|
assertThat(p.getMeta().getTag(), empty());
|
||||||
|
assertThat(p.getMeta().getTag("foo", "bar"), nullValue());
|
||||||
|
assertThat(p.getMeta().getVersionId(), nullValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeCompleteMetaLists() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.getMeta().addProfile("http://foo/profile1");
|
||||||
|
p.getMeta().addProfile("http://foo/profile2");
|
||||||
|
p.getMeta().addSecurity().setSystem("SEC_S1").setCode("SEC_C1").setDisplay("SED_D1");
|
||||||
|
p.getMeta().addSecurity().setSystem("SEC_S2").setCode("SEC_C2").setDisplay("SED_D2");
|
||||||
|
p.getMeta().addTag().setSystem("TAG_S1").setCode("TAG_C1").setDisplay("TAG_D1");
|
||||||
|
p.getMeta().addTag().setSystem("TAG_S2").setCode("TAG_C2").setDisplay("TAG_D2");
|
||||||
|
|
||||||
|
String out = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||||
|
ourLog.info(out);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(out, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://foo/profile1\"/>",
|
||||||
|
"<profile value=\"http://foo/profile2\"/>",
|
||||||
|
"<security>",
|
||||||
|
"<system value=\"SEC_S1\"/>",
|
||||||
|
"<code value=\"SEC_C1\"/>",
|
||||||
|
"<display value=\"SED_D1\"/>",
|
||||||
|
"</security>",
|
||||||
|
"<security>",
|
||||||
|
"<system value=\"SEC_S2\"/>",
|
||||||
|
"<code value=\"SEC_C2\"/>",
|
||||||
|
"<display value=\"SED_D2\"/>",
|
||||||
|
"</security>",
|
||||||
|
"<tag>",
|
||||||
|
"<system value=\"TAG_S1\"/>",
|
||||||
|
"<display value=\"TAG_D1\"/>",
|
||||||
|
"</tag>",
|
||||||
|
"<tag>",
|
||||||
|
"<system value=\"TAG_S2\"/>",
|
||||||
|
"<display value=\"TAG_D2\"/>",
|
||||||
|
"</tag>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeWithCustomType() {
|
||||||
|
|
||||||
MyCustomPatient patient = new MyCustomPatient();
|
MyCustomPatient patient = new MyCustomPatient();
|
||||||
|
|
||||||
|
@ -36,17 +243,76 @@ public class CustomTypeDstu3Test {
|
||||||
patient.setCholesterol(new Quantity());
|
patient.setCholesterol(new Quantity());
|
||||||
patient.setWeight(new StringDt("80 kg"));
|
patient.setWeight(new StringDt("80 kg"));
|
||||||
patient.setWeight(new StringDt("185 cm"));
|
patient.setWeight(new StringDt("185 cm"));
|
||||||
patient.setCheckDates(new ArrayList<DateTimeType>());
|
patient.setCheckDates(new ArrayList<DateTimeDt>());
|
||||||
patient.getCheckDates().add(new DateTimeType("2014-01-26T11:11:11"));
|
patient.getCheckDates().add(new DateTimeDt("2014-01-26T11:11:11"));
|
||||||
|
|
||||||
IParser p = ctx.newXmlParser().setPrettyPrint(true);
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
String messageString = p.encodeResourceToString(patient);
|
String messageString = p.encodeResourceToString(patient);
|
||||||
|
|
||||||
ourLog.info(messageString);
|
ourLog.info(messageString);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, not(stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"", "/>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>")));
|
||||||
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResourceDef(name = "Patient")
|
@Test
|
||||||
|
public void testEncodeWithCustomTypeAndAutoInsertedProfile() {
|
||||||
|
|
||||||
|
MyCustomPatient patient = new MyCustomPatient();
|
||||||
|
|
||||||
|
patient.getMeta().addProfile("http://example.com/foo");
|
||||||
|
patient.getMeta().addProfile("http://example.com/bar");
|
||||||
|
|
||||||
|
patient.addIdentifier().setSystem("urn:system").setValue("1234");
|
||||||
|
patient.addName().addFamily("Rossi").addGiven("Mario");
|
||||||
|
patient.setInsulinLevel(new Quantity());
|
||||||
|
patient.setGlucoseLevel(new Quantity());
|
||||||
|
patient.setHbA1c(new Quantity());
|
||||||
|
patient.setBloodPressure(new Quantity());
|
||||||
|
patient.setCholesterol(new Quantity());
|
||||||
|
patient.setWeight(new StringDt("80 kg"));
|
||||||
|
patient.setWeight(new StringDt("185 cm"));
|
||||||
|
patient.setCheckDates(new ArrayList<DateTimeDt>());
|
||||||
|
patient.getCheckDates().add(new DateTimeDt("2014-01-26T11:11:11"));
|
||||||
|
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
String messageString = p.encodeResourceToString(patient);
|
||||||
|
|
||||||
|
ourLog.info(messageString);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"<profile value=\"http://example.com/bar\"/>",
|
||||||
|
"</meta>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(messageString, not(stringContainsInOrder(
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/foo\"", "/>",
|
||||||
|
"<profile value=\"http://example.com/foo\"/>",
|
||||||
|
"</meta>")));
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ResourceDef(name = "Patient", profile = "http://example.com/foo")
|
||||||
public static class MyCustomPatient extends Patient {
|
public static class MyCustomPatient extends Patient {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -60,7 +326,7 @@ public class CustomTypeDstu3Test {
|
||||||
@Child(name = "CheckDates", max = Child.MAX_UNLIMITED)
|
@Child(name = "CheckDates", max = Child.MAX_UNLIMITED)
|
||||||
@Extension(url = "http://example.com/diabetes2", definedLocally = false, isModifier = true)
|
@Extension(url = "http://example.com/diabetes2", definedLocally = false, isModifier = true)
|
||||||
@Description(shortDefinition = "Dates of periodic tests")
|
@Description(shortDefinition = "Dates of periodic tests")
|
||||||
private List<DateTimeType> myCheckDates;
|
private List<DateTimeDt> myCheckDates;
|
||||||
|
|
||||||
@Child(name = "cholesterol") // once a year. The target is triglycerides =< 2 mmol/l e cholesterol =< 4 mmol/l
|
@Child(name = "cholesterol") // once a year. The target is triglycerides =< 2 mmol/l e cholesterol =< 4 mmol/l
|
||||||
@Extension(url = "http://example.com/Cholesterol", definedLocally = false, isModifier = false)
|
@Extension(url = "http://example.com/Cholesterol", definedLocally = false, isModifier = false)
|
||||||
|
@ -116,9 +382,9 @@ public class CustomTypeDstu3Test {
|
||||||
return myBloodPressure;
|
return myBloodPressure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DateTimeType> getCheckDates() {
|
public List<DateTimeDt> getCheckDates() {
|
||||||
if (myCheckDates == null) {
|
if (myCheckDates == null) {
|
||||||
myCheckDates = new ArrayList<DateTimeType>();
|
myCheckDates = new ArrayList<DateTimeDt>();
|
||||||
}
|
}
|
||||||
return myCheckDates;
|
return myCheckDates;
|
||||||
}
|
}
|
||||||
|
@ -182,9 +448,9 @@ public class CustomTypeDstu3Test {
|
||||||
myBloodPressure.setCode("mmHg");
|
myBloodPressure.setCode("mmHg");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCheckDates(List<DateTimeType> theCheckDates) {
|
public void setCheckDates(List<DateTimeDt> theCheckDates) {
|
||||||
myCheckDates = theCheckDates;
|
myCheckDates = theCheckDates;
|
||||||
myCheckDates.add(new DateTimeType("2010-01-02"));
|
myCheckDates.add(new DateTimeDt("2010-01-02"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCholesterol(Quantity cholesterol) {
|
public void setCholesterol(Quantity cholesterol) {
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.io.input.ReaderInputStream;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolVersion;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.message.BasicHeader;
|
||||||
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.hl7.fhir.dstu3.model.Binary;
|
||||||
|
import org.hl7.fhir.dstu3.model.Conformance;
|
||||||
|
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
|
|
||||||
|
public class ClientWithCustomTypeDstu3Test {
|
||||||
|
private static FhirContext ourCtx;
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientWithCustomTypeDstu3Test.class);
|
||||||
|
private HttpClient myHttpClient;
|
||||||
|
private HttpResponse myHttpResponse;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||||
|
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||||
|
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
|
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] extractBodyAsByteArray(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||||
|
byte[] body = IOUtils.toByteArray(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent());
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||||
|
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadCustomType() throws Exception {
|
||||||
|
IParser p = ourCtx.newXmlParser();
|
||||||
|
|
||||||
|
MyPatientWithExtensions response = new MyPatientWithExtensions();
|
||||||
|
response.addName().addFamily("FAMILY");
|
||||||
|
response.getStringExt().setValue("STRINGVAL");
|
||||||
|
response.getDateExt().setValueAsString("2011-01-02");
|
||||||
|
final String respString = p.encodeResourceToString(response);
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
|
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||||
|
@Override
|
||||||
|
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||||
|
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
MyPatientWithExtensions value = client
|
||||||
|
.read()
|
||||||
|
.resource(MyPatientWithExtensions.class)
|
||||||
|
.withId("123")
|
||||||
|
.execute();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
HttpUriRequest request = capt.getAllValues().get(0);
|
||||||
|
|
||||||
|
assertEquals("http://example.com/fhir/Patient/123", request.getURI().toASCIIString());
|
||||||
|
assertEquals("GET", request.getMethod());
|
||||||
|
|
||||||
|
assertEquals(1, value.getName().size());
|
||||||
|
assertEquals("FAMILY", value.getName().get(0).getFamilyAsSingleString());
|
||||||
|
assertEquals("STRINGVAL", value.getStringExt().getValue());
|
||||||
|
assertEquals("2011-01-02", value.getDateExt().getValueAsString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() {
|
||||||
|
ourCtx = FhirContext.forDstu3();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.BaseResource;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
|
import org.hl7.fhir.dstu3.model.DomainResource;
|
||||||
|
import org.hl7.fhir.dstu3.model.HumanName;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.ResourceType;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
|
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.util.ElementUtil;
|
||||||
|
|
||||||
|
|
||||||
|
@ResourceDef(name="Patient", profile="http://example.com/StructureDefinition/patient_with_extensions")
|
||||||
|
public class MyPatientWithExtensions extends DomainResource {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Extension(url = "http://example.com/ext/date", definedLocally = false, isModifier = true)
|
||||||
|
@Child(name = "modExt")
|
||||||
|
private DateType myDateExt;
|
||||||
|
|
||||||
|
@Extension(url = "http://example.com/ext/string", definedLocally = false, isModifier = false)
|
||||||
|
@Child(name = "extAtt")
|
||||||
|
private StringType myStringExt;
|
||||||
|
|
||||||
|
@Child(name = "name", type = {HumanName.class}, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true)
|
||||||
|
@Description(shortDefinition="A name associated with the patient", formalDefinition="A name associated with the individual." )
|
||||||
|
private List<HumanName> myName;
|
||||||
|
|
||||||
|
|
||||||
|
public List<HumanName> getName() {
|
||||||
|
if (myName == null) {
|
||||||
|
myName = new ArrayList<HumanName>();
|
||||||
|
}
|
||||||
|
return myName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(List<HumanName> theName) {
|
||||||
|
myName = theName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateType getDateExt() {
|
||||||
|
if (myDateExt == null) {
|
||||||
|
myDateExt = new DateType();
|
||||||
|
}
|
||||||
|
return myDateExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringType getStringExt() {
|
||||||
|
if (myStringExt == null) {
|
||||||
|
myStringExt = new StringType();
|
||||||
|
}
|
||||||
|
return myStringExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return super.isEmpty() && ElementUtil.isEmpty(myStringExt, myDateExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDateExt(DateType theDateExt) {
|
||||||
|
myDateExt = theDateExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringExt(StringType theStringExt) {
|
||||||
|
myStringExt = theStringExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResource copy() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceType getResourceType() {
|
||||||
|
return ResourceType.Patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HumanName addName() {
|
||||||
|
HumanName retVal = new HumanName();
|
||||||
|
getName().add(retVal);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
@ -10,120 +12,88 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.entity.ContentType;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
|
||||||
public class CreateDstu3Test {
|
public class CreateDstu3Test {
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
|
|
||||||
private static String ourLastConditionalUrl;
|
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateDstu3Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateDstu3Test.class);
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static IdType ourLastId;
|
|
||||||
private static IdType ourLastIdParam;
|
|
||||||
private static boolean ourLastRequestWasSearch;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void before() {
|
|
||||||
ourLastId = null;
|
|
||||||
ourLastConditionalUrl = null;
|
|
||||||
ourLastIdParam = null;
|
|
||||||
ourLastRequestWasSearch = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithIdInBody() throws Exception {
|
public void testRead() throws Exception {
|
||||||
|
|
||||||
Patient patient = new Patient();
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2?_format=xml&_pretty=true");
|
||||||
patient.setId("2");
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
patient.addIdentifier().setValue("002");
|
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
|
||||||
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
|
||||||
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
|
||||||
assertEquals("Can not create resource with ID \"2\", an ID element must not be supplied in the resource body on a create (POST) operation", oo.getIssue().get(0).getDiagnostics());
|
//@formatter:off
|
||||||
|
assertThat(responseContent, stringContainsInOrder("<Patient xmlns=\"http://hl7.org/fhir\">",
|
||||||
|
"<id value=\"2\"/>",
|
||||||
|
"<modifierExtension url=\"http://example.com/ext/date\">",
|
||||||
|
"<valueDate value=\"2011-01-01\"/>",
|
||||||
|
"</modifierExtension>",
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/StructureDefinition/patient_with_extensions\"/>",
|
||||||
|
"</meta>",
|
||||||
|
"</Patient>"));
|
||||||
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithIdInUrl() throws Exception {
|
public void testSearch() throws Exception {
|
||||||
|
|
||||||
Patient patient = new Patient();
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=xml&_pretty=true");
|
||||||
patient.addIdentifier().setValue("002");
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
|
|
||||||
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
|
||||||
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
|
||||||
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
//@formatter:off
|
||||||
public void testCreateWithIdInUrlForConditional() throws Exception {
|
assertThat(responseContent, stringContainsInOrder("<Patient xmlns=\"http://hl7.org/fhir\">",
|
||||||
|
"<id value=\"0\"/>",
|
||||||
|
"<modifierExtension url=\"http://example.com/ext/date\">",
|
||||||
|
"<valueDate value=\"2011-01-01\"/>",
|
||||||
|
"</modifierExtension>",
|
||||||
|
"<meta>",
|
||||||
|
"<profile value=\"http://example.com/StructureDefinition/patient_with_extensions\"/>",
|
||||||
|
"</meta>",
|
||||||
|
"</Patient>"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
Patient patient = new Patient();
|
assertThat(responseContent, not(containsString("http://hl7.org/fhir/")));
|
||||||
patient.addIdentifier().setValue("002");
|
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
|
|
||||||
httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
|
||||||
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
|
||||||
|
|
||||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
|
||||||
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
|
||||||
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
@ -140,6 +110,7 @@ public class CreateDstu3Test {
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||||
|
|
||||||
servlet.setResourceProviders(patientProvider);
|
servlet.setResourceProviders(patientProvider);
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
@ -160,18 +131,29 @@ public class CreateDstu3Test {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search
|
@Read()
|
||||||
public List<IResource> search(@OptionalParam(name = "foo") StringDt theString) {
|
public MyPatientWithExtensions read(@IdParam IdType theIdParam) {
|
||||||
ourLastRequestWasSearch = true;
|
MyPatientWithExtensions p0 = new MyPatientWithExtensions();
|
||||||
return new ArrayList<IResource>();
|
p0.setId(theIdParam);
|
||||||
|
p0.setDateExt(new DateType("2011-01-01"));
|
||||||
|
return p0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Create()
|
@Search
|
||||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @ConditionalUrlParam String theConditional, @IdParam IdType theIdParam) {
|
public List<IBaseResource> search() {
|
||||||
ourLastConditionalUrl = theConditional;
|
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||||
ourLastId = thePatient.getIdElement();
|
|
||||||
ourLastIdParam = theIdParam;
|
MyPatientWithExtensions p0 = new MyPatientWithExtensions();
|
||||||
return new MethodOutcome(new IdType("Patient/001/_history/002"));
|
p0.setId(new IdType("Patient/0"));
|
||||||
|
p0.setDateExt(new DateType("2011-01-01"));
|
||||||
|
retVal.add(p0);
|
||||||
|
|
||||||
|
Patient p1 = new Patient();
|
||||||
|
p1.setId(new IdType("Patient/1"));
|
||||||
|
p1.addName().addFamily("The Family");
|
||||||
|
retVal.add(p1);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
|
||||||
|
public class CustomTypeServerDstu3 {
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
|
||||||
|
private static String ourLastConditionalUrl;
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomTypeServerDstu3.class);
|
||||||
|
private static int ourPort;
|
||||||
|
private static Server ourServer;
|
||||||
|
private static IdType ourLastId;
|
||||||
|
private static IdType ourLastIdParam;
|
||||||
|
private static boolean ourLastRequestWasSearch;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ourLastId = null;
|
||||||
|
ourLastConditionalUrl = null;
|
||||||
|
ourLastIdParam = null;
|
||||||
|
ourLastRequestWasSearch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithIdInBody() throws Exception {
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId("2");
|
||||||
|
patient.addIdentifier().setValue("002");
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
|
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
||||||
|
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||||
|
assertEquals("Can not create resource with ID \"2\", an ID element must not be supplied in the resource body on a create (POST) operation", oo.getIssue().get(0).getDiagnostics());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithIdInUrl() throws Exception {
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier().setValue("002");
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
|
||||||
|
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
||||||
|
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||||
|
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithIdInUrlForConditional() throws Exception {
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier().setValue("002");
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
|
||||||
|
httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
|
||||||
|
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||||
|
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClass() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourPort = PortUtil.findFreePort();
|
||||||
|
ourServer = new Server(ourPort);
|
||||||
|
|
||||||
|
PatientProvider patientProvider = new PatientProvider();
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||||
|
servlet.setResourceProviders(patientProvider);
|
||||||
|
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
ourServer.start();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PatientProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public List<IResource> search(@OptionalParam(name = "foo") StringDt theString) {
|
||||||
|
ourLastRequestWasSearch = true;
|
||||||
|
return new ArrayList<IResource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Create()
|
||||||
|
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @ConditionalUrlParam String theConditional, @IdParam IdType theIdParam) {
|
||||||
|
ourLastConditionalUrl = theConditional;
|
||||||
|
ourLastId = thePatient.getIdElement();
|
||||||
|
ourLastIdParam = theIdParam;
|
||||||
|
return new MethodOutcome(new IdType("Patient/001/_history/002"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,10 +48,8 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
@ -59,7 +57,6 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.IRestfulServer;
|
import ca.uhn.fhir.rest.server.IRestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||||
|
@ -298,7 +295,7 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult,
|
public void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult,
|
||||||
EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
||||||
int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
||||||
myBase = theServerBase;
|
myBase = theServerBase;
|
||||||
|
@ -344,15 +341,6 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
|
||||||
for (IBaseResource nextRes : resourceList) {
|
|
||||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
|
||||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
|
||||||
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
|
||||||
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType,
|
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType,
|
||||||
theResult.getPublished());
|
theResult.getPublished());
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.hl7.fhir.instance.model.StringType;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.INarrative;
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -67,11 +68,11 @@ import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
|
||||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredAddressExtension;
|
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredAddressExtension;
|
||||||
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredEnumerationExtension;
|
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredEnumerationExtension;
|
||||||
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredExtension;
|
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredExtension;
|
||||||
|
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import net.sf.json.JSON;
|
import net.sf.json.JSON;
|
||||||
import net.sf.json.JSONSerializer;
|
import net.sf.json.JSONSerializer;
|
||||||
|
@ -81,6 +82,11 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
private static FhirContext ourCtx;
|
private static FhirContext ourCtx;
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserHl7OrgDstu2Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserHl7OrgDstu2Test.class);
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
private String fixDivNodeText(String htmlNoNs) {
|
private String fixDivNodeText(String htmlNoNs) {
|
||||||
return htmlNoNs.replace("<div>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">");
|
return htmlNoNs.replace("<div>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">");
|
||||||
}
|
}
|
||||||
|
@ -89,25 +95,6 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
return htmlNoNs.replace("<div>", "<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">");
|
return htmlNoNs.replace("<div>", "<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
|
|
||||||
*
|
|
||||||
* Disabled after conversation with Grahame
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
|
||||||
IParser xmlParser = ourCtx.newXmlParser();
|
|
||||||
|
|
||||||
String input = IOUtils.toString(XmlParser.class.getResourceAsStream("/medicationstatement_invalidelement.xml"));
|
|
||||||
MedicationStatement ms = xmlParser.parseResource(MedicationStatement.class, input);
|
|
||||||
SimpleQuantity q = (SimpleQuantity) ms.getDosage().get(0).getQuantity();
|
|
||||||
assertEquals("1", q.getValueElement().getValueAsString());
|
|
||||||
|
|
||||||
String output = xmlParser.encodeResourceToString(ms);
|
|
||||||
assertThat(output, containsString("<quantityQuantity><value value=\"1\"/></quantityQuantity>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComposition() {
|
public void testComposition() {
|
||||||
|
@ -575,6 +562,26 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
|
||||||
|
*
|
||||||
|
* Disabled after conversation with Grahame
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
||||||
|
IParser xmlParser = ourCtx.newXmlParser();
|
||||||
|
|
||||||
|
String input = IOUtils.toString(XmlParser.class.getResourceAsStream("/medicationstatement_invalidelement.xml"));
|
||||||
|
MedicationStatement ms = xmlParser.parseResource(MedicationStatement.class, input);
|
||||||
|
SimpleQuantity q = (SimpleQuantity) ms.getDosage().get(0).getQuantity();
|
||||||
|
assertEquals("1", q.getValueElement().getValueAsString());
|
||||||
|
|
||||||
|
String output = xmlParser.encodeResourceToString(ms);
|
||||||
|
assertThat(output, containsString("<quantityQuantity><value value=\"1\"/></quantityQuantity>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeBinaryResource() {
|
public void testEncodeBinaryResource() {
|
||||||
|
|
||||||
|
@ -587,7 +594,6 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeBinaryWithNoContentType() {
|
public void testEncodeBinaryWithNoContentType() {
|
||||||
Binary b = new Binary();
|
Binary b = new Binary();
|
||||||
|
@ -613,7 +619,6 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
assertThat(val, containsString("home"));
|
assertThat(val, containsString("home"));
|
||||||
assertThat(val, containsString("male"));
|
assertThat(val, containsString("male"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeBundle() throws InterruptedException {
|
public void testEncodeBundle() throws InterruptedException {
|
||||||
Bundle b = new Bundle();
|
Bundle b = new Bundle();
|
||||||
|
@ -650,6 +655,7 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings));
|
assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeBundleCategory() {
|
public void testEncodeBundleCategory() {
|
||||||
|
|
||||||
|
@ -718,6 +724,7 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
|
public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
|
||||||
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
@ -745,7 +752,6 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeDeclaredExtensionWithAddressContent() {
|
public void testEncodeDeclaredExtensionWithAddressContent() {
|
||||||
IParser parser = ourCtx.newXmlParser();
|
IParser parser = ourCtx.newXmlParser();
|
||||||
|
@ -1110,6 +1116,7 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtensionOnComposite() throws Exception {
|
public void testExtensionOnComposite() throws Exception {
|
||||||
|
|
||||||
|
@ -1133,7 +1140,6 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtensionOnPrimitive() throws Exception {
|
public void testExtensionOnPrimitive() throws Exception {
|
||||||
|
|
||||||
|
@ -1219,6 +1225,7 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
@Test
|
@Test
|
||||||
public void testLoadAndEncodeDeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException {
|
public void testLoadAndEncodeDeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException {
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
|
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER);
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
String msg = "<ResourceWithExtensionsA xmlns=\"http://hl7.org/fhir\">\n" +
|
String msg = "<ResourceWithExtensionsA xmlns=\"http://hl7.org/fhir\">\n" +
|
||||||
|
|
|
@ -26,9 +26,6 @@ import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by dsotnikov on 2/25/2014.
|
|
||||||
*/
|
|
||||||
public class BundleTypeInResponseHl7OrgTest {
|
public class BundleTypeInResponseHl7OrgTest {
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
package ca.uhn.fhir.model.dstu2.resource;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* #%L
|
|
||||||
* HAPI FHIR Structures - DSTU2 (FHIR v0.4.0)
|
|
||||||
* %%
|
|
||||||
* Copyright (C) 2014 - 2015 University Health Network
|
|
||||||
* %%
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* #L%
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.BaseElement;
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
|
||||||
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
|
||||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
|
|
||||||
import ca.uhn.fhir.model.dstu2.composite.NarrativeDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
|
||||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
|
||||||
|
|
||||||
public abstract class BaseResource extends BaseElement implements IResource {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_language</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
|
|
||||||
public static final String SP_RES_LANGUAGE = "_language";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search parameter constant for <b>_id</b>
|
|
||||||
*/
|
|
||||||
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
|
|
||||||
public static final String SP_RES_ID = "_id";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
|
|
||||||
* <p>
|
|
||||||
* Description: <b>the _id of a resource</b><br>
|
|
||||||
* Type: <b>string</b><br>
|
|
||||||
* Path: <b>Resource._id</b><br>
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
|
|
||||||
|
|
||||||
|
|
||||||
@Child(name = "contained", order = 2, min = 0, max = 1)
|
|
||||||
private ContainedDt myContained;
|
|
||||||
|
|
||||||
private IdDt myId;
|
|
||||||
|
|
||||||
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
|
||||||
private CodeDt myLanguage;
|
|
||||||
|
|
||||||
private ResourceMetadataMap myResourceMetadata;
|
|
||||||
|
|
||||||
@Child(name = "text", order = 1, min = 0, max = 1)
|
|
||||||
private NarrativeDt myText;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContainedDt getContained() {
|
|
||||||
if (myContained == null) {
|
|
||||||
myContained = new ContainedDt();
|
|
||||||
}
|
|
||||||
return myContained;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IdDt getId() {
|
|
||||||
if (myId == null) {
|
|
||||||
myId = new IdDt();
|
|
||||||
}
|
|
||||||
return myId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IIdType getIdElement() {
|
|
||||||
return getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CodeDt getLanguage() {
|
|
||||||
if (myLanguage == null) {
|
|
||||||
myLanguage = new CodeDt();
|
|
||||||
}
|
|
||||||
return myLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceMetadataMap getResourceMetadata() {
|
|
||||||
if (myResourceMetadata == null) {
|
|
||||||
myResourceMetadata = new ResourceMetadataMap();
|
|
||||||
}
|
|
||||||
return myResourceMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NarrativeDt getText() {
|
|
||||||
if (myText == null) {
|
|
||||||
myText = new NarrativeDt();
|
|
||||||
}
|
|
||||||
return myText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContained(ContainedDt theContained) {
|
|
||||||
myContained = theContained;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(IdDt theId) {
|
|
||||||
myId = theId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseResource setId(IIdType theId) {
|
|
||||||
if (theId instanceof IdDt) {
|
|
||||||
myId = (IdDt) theId;
|
|
||||||
} else if (theId != null) {
|
|
||||||
myId = new IdDt(theId.getValue());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseResource setId(String theId) {
|
|
||||||
if (theId == null) {
|
|
||||||
myId = null;
|
|
||||||
} else {
|
|
||||||
myId = new IdDt(theId);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLanguage(CodeDt theLanguage) {
|
|
||||||
myLanguage = theLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setResourceMetadata(ResourceMetadataMap theMap) {
|
|
||||||
Validate.notNull(theMap, "The Map must not be null");
|
|
||||||
myResourceMetadata = theMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setText(NarrativeDt theText) {
|
|
||||||
myText = theText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
|
||||||
b.append("id", getId().toUnqualified());
|
|
||||||
return b.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
|
|
||||||
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isBaseEmpty() {
|
|
||||||
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -51,6 +51,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#foreach ( $child in $childElements )
|
#foreach ( $child in $childElements )
|
||||||
|
#if (${child.methodName} != 'Meta')
|
||||||
/**
|
/**
|
||||||
* Gets the value(s) for <b>${child.elementName}</b> ($esc.html(${child.shortName})).
|
* Gets the value(s) for <b>${child.elementName}</b> ($esc.html(${child.shortName})).
|
||||||
* creating it if it does
|
* creating it if it does
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
#end
|
#end
|
||||||
return ${child.variableName};
|
return ${child.variableName};
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value(s) for <b>${child.elementName}</b> ($esc.html(${child.shortName})).
|
* Gets the value(s) for <b>${child.elementName}</b> ($esc.html(${child.shortName})).
|
||||||
|
|
|
@ -261,6 +261,44 @@
|
||||||
header containing "application/xml" as some browsers
|
header containing "application/xml" as some browsers
|
||||||
do.
|
do.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
DSTU2 resources now have a
|
||||||
|
<![CDATA[<code>getMeta()</code>]]> method which returns a
|
||||||
|
modifiable view of the resource metadata for convenience. This
|
||||||
|
matches the equivalent method in the DSTU3 structures.
|
||||||
|
</action>
|
||||||
|
<action type="add" issue="315">
|
||||||
|
Add a new method to FhirContext called
|
||||||
|
<![CDATA[
|
||||||
|
<code><a href="./apidocs/ca/uhn/fhir/context/FhirContext.html#setDefaultTypeForProfile-java.lang.String-java.lang.Class-">setDefaultTypeForProfile</a></code>
|
||||||
|
]]>
|
||||||
|
which can be used to specify that when recources are received which declare
|
||||||
|
support for specific profiles, a specific custom structures should be used
|
||||||
|
instead of the default. For example, if you have created a custom Observation
|
||||||
|
class for a specific profile, you could use this method to cause your custom
|
||||||
|
type to be used by the parser for resources in a search bundle you receive.
|
||||||
|
<![CDATA[
|
||||||
|
<br/><br/>
|
||||||
|
See the documentation page on
|
||||||
|
<a href="./doc_extensions.html">Profiles and Extensions</a>
|
||||||
|
for more information.
|
||||||
|
]]>
|
||||||
|
</action>
|
||||||
|
<action type="fix" issue="315">
|
||||||
|
Parsing/Encoding a custom resource type which extends a
|
||||||
|
base type sometimes caused the FhirContext to treat all future
|
||||||
|
parses of the same resource as using the custom type even when
|
||||||
|
this was not wanted.
|
||||||
|
<![CDATA[<br/><br/>]]>
|
||||||
|
Custom structures may now be explicitly declared by profile
|
||||||
|
using the
|
||||||
|
<![CDATA[
|
||||||
|
<code><a href="./apidocs/ca/uhn/fhir/context/FhirContext.html#setDefaultTypeForProfile-java.lang.String-java.lang.Class-">setDefaultTypeForProfile</a></code>
|
||||||
|
]]>
|
||||||
|
method.
|
||||||
|
<![CDATA[<br/><br/>]]>
|
||||||
|
This issue was discovered and fixed as a part of the implementation of issue #315.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="1.4" date="2016-02-04">
|
<release version="1.4" date="2016-02-04">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
|
@ -3,13 +3,20 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<title>Profiles and Extensions</title>
|
<title>Profiles and Extensions</title>
|
||||||
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
<author email="jamesagnew@gmail.com">James Agnew</author>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section name="Undeclared Extensions">
|
<section name="Undeclared Extensions">
|
||||||
|
|
||||||
|
<p class="doc_info_bubble">
|
||||||
|
Note on FHIR Versions: Because of the differences in the way the structures
|
||||||
|
work between DSTU2 and DSTU3, we have provided two versions of many of the
|
||||||
|
examples on this page. See the <a href="./download.html">download page</a>
|
||||||
|
for more information on FHIR versions.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Extensions are a key part of the FHIR specification, providing a standardized
|
Extensions are a key part of the FHIR specification, providing a standardized
|
||||||
way of placing additional data in a resource.
|
way of placing additional data in a resource.
|
||||||
|
@ -21,17 +28,40 @@
|
||||||
Undeclared extensions can be added to any of the built in FHIR resource types that come with HAPI-FHIR.
|
Undeclared extensions can be added to any of the built in FHIR resource types that come with HAPI-FHIR.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU2</b>
|
||||||
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="resourceExtension" />
|
<param name="id" value="resourceExtension" />
|
||||||
<param name="file" value="examples/src/main/java/example/Extensions.java" />
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu2.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU3</b>
|
||||||
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="resourceExtension" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Undeclared extensions can also be added to datatypes (composite or primitive).
|
Undeclared extensions can also be added to datatypes (composite or primitive).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU2</b>
|
||||||
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="resourceStringExtension" />
|
<param name="id" value="resourceStringExtension" />
|
||||||
<param name="file" value="examples/src/main/java/example/Extensions.java" />
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu2.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU3</b>
|
||||||
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="resourceStringExtension" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<subsection name="Sub-Extensions">
|
<subsection name="Sub-Extensions">
|
||||||
|
@ -41,9 +71,21 @@
|
||||||
of a datatype. This is done by adding a child undeclared extension to the
|
of a datatype. This is done by adding a child undeclared extension to the
|
||||||
parent extension.
|
parent extension.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU2</b>
|
||||||
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="subExtension" />
|
<param name="id" value="subExtension" />
|
||||||
<param name="file" value="examples/src/main/java/example/Extensions.java" />
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu2.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU3</b>
|
||||||
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="subExtension" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
</subsection>
|
</subsection>
|
||||||
|
@ -52,11 +94,23 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
HAPI provides a few ways of accessing extension values in resources
|
HAPI provides a few ways of accessing extension values in resources
|
||||||
which are receieved from other sources (i.e. downloaded by a client).
|
which are received from other sources (i.e. downloaded by a client).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU2</b>
|
||||||
</p>
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="parseExtension" />
|
<param name="id" value="parseExtension" />
|
||||||
<param name="file" value="examples/src/main/java/example/Extensions.java" />
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu2.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>DSTU3</b>
|
||||||
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="parseExtension" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
</subsection>
|
</subsection>
|
||||||
|
@ -119,84 +173,43 @@
|
||||||
<param name="file" value="examples/src/main/java/example/MyPatientUse.java" />
|
<param name="file" value="examples/src/main/java/example/MyPatientUse.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<subsection name="Documentation">
|
<subsection name="Using Custom Types in a Client">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Note in the example above the use of the <code>@Description</code>
|
If you are using a client and wish to use a specific custom structure,
|
||||||
annotation on the extension fields. This documentation is important,
|
you may simply use the custom structure as you would a build in
|
||||||
as the FHIR Server will automatically add it to the generated Profile
|
HAPI type.
|
||||||
resources which are exported by the server.
|
|
||||||
</p>
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="customTypeClientSimple" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
These bits of documentation will then be re-added to any automatically
|
Sometimes you may not know in advance exactly which
|
||||||
generated clients built using <a href="./doc_tinder.html">Tinder</a>
|
type you will be receiving. For example, there are Patient resources
|
||||||
against your server.
|
which conform to several different profiles on a server and you
|
||||||
|
aren't sure which profile you will get back for a specific read,
|
||||||
|
you can declare the "primary" type for a given profile.
|
||||||
</p>
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="customTypeClientDeclared" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
<subsection name="Using Custom Types in a Server">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The following is a snippet from the generated Profile resource
|
If you are using a client and wish to use a specific custom structure,
|
||||||
which is automatically created by a HAPI RESTful server using
|
you may simply use the custom structure as you would a build in
|
||||||
your new type. (Don't worry if this part doens't make sense to you
|
HAPI type.
|
||||||
yet, this is an advanced feature)
|
|
||||||
</p>
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
<source><![CDATA[<element>
|
<param name="id" value="customTypeClientSimple" />
|
||||||
<path value="Patient.extension"/>
|
<param name="file" value="examples/src/main/java/example/ExtensionsDstu3.java" />
|
||||||
<name value="extension"/>
|
</macro>
|
||||||
<slicing>
|
|
||||||
<discriminator value="url"/>
|
|
||||||
<ordered value="false"/>
|
|
||||||
<rules value="open"/>
|
|
||||||
</slicing>
|
|
||||||
<definition>
|
|
||||||
<type>
|
|
||||||
<code value="Extension"/>
|
|
||||||
</type>
|
|
||||||
</definition>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<path value="Patient.extension"/>
|
|
||||||
<name value="extension"/>
|
|
||||||
<definition>
|
|
||||||
<short value="The name of the patient's favourite pet"/>
|
|
||||||
<min value="0"/>
|
|
||||||
<max value="1"/>
|
|
||||||
<type>
|
|
||||||
<code value="Extension"/>
|
|
||||||
<profile value="http://example.com/dontuse#petname"/>
|
|
||||||
</type>
|
|
||||||
<isModifier value="false"/>
|
|
||||||
</definition>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<path value="Patient.modifierExtension"/>
|
|
||||||
<name value="modifierExtension"/>
|
|
||||||
<slicing>
|
|
||||||
<discriminator value="url"/>
|
|
||||||
<ordered value="false"/>
|
|
||||||
<rules value="open"/>
|
|
||||||
</slicing>
|
|
||||||
<definition>
|
|
||||||
<type>
|
|
||||||
<code value="Extension"/>
|
|
||||||
</type>
|
|
||||||
</definition>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<path value="Patient.modifierExtension"/>
|
|
||||||
<name value="modifierExtension"/>
|
|
||||||
<definition>
|
|
||||||
<short value="Some dates of note for the patient"/>
|
|
||||||
<min value="0"/>
|
|
||||||
<max value="*"/>
|
|
||||||
<type>
|
|
||||||
<code value="Extension"/>
|
|
||||||
<profile value="http://example.com/dontuse#importantDates"/>
|
|
||||||
</type>
|
|
||||||
<isModifier value="true"/>
|
|
||||||
</definition>
|
|
||||||
</element>]]></source>
|
|
||||||
|
|
||||||
</subsection>
|
</subsection>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue