Merge branch 'master' of https://github.com/jamesagnew/hapi-fhir
This commit is contained in:
commit
e190659fcf
|
@ -8,6 +8,7 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
||||
|
@ -36,6 +37,9 @@ public class PlainProvider {
|
|||
//START SNIPPET: plainProviderServer
|
||||
public class ExampleServlet extends RestfulServer {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ExampleServlet() {
|
||||
/*
|
||||
* Plain providers are passed to the server in the same way
|
||||
|
@ -54,5 +58,25 @@ public class ExampleServlet extends RestfulServer {
|
|||
}
|
||||
//END SNIPPET: plainProviderServer
|
||||
|
||||
//START SNIPPET: addressStrategy
|
||||
public class MyServlet extends RestfulServer {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MyServlet() {
|
||||
|
||||
String serverBaseUrl = "http://foo.com/fhir";
|
||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverBaseUrl));
|
||||
|
||||
// ...add some resource providers, etc...
|
||||
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
|
||||
setResourceProviders(resourceProviders);
|
||||
}
|
||||
|
||||
}
|
||||
//END SNIPPET: addressStrategy
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.model.base.resource.BaseConformance;
|
|||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -68,6 +69,30 @@ public class GenericClientExample {
|
|||
System.out.println("Got ID: " + id.getValue());
|
||||
// END SNIPPET: create
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
// START SNIPPET: createConditional
|
||||
// One form
|
||||
MethodOutcome outcome = client.create()
|
||||
.resource(patient)
|
||||
.conditionalByUrl("Patient?identifier=system%7C00001")
|
||||
.execute();
|
||||
|
||||
// Another form
|
||||
MethodOutcome outcome2 = client.create()
|
||||
.resource(patient)
|
||||
.conditional()
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||
.execute();
|
||||
|
||||
// This will return true if the server responded with an HTTP 201 created,
|
||||
// otherwise it will return null.
|
||||
Boolean created = outcome.getCreated();
|
||||
|
||||
// The ID of the created, or the pre-existing resource
|
||||
IdDt id = outcome.getId();
|
||||
// END SNIPPET: createConditional
|
||||
}
|
||||
{
|
||||
// START SNIPPET: update
|
||||
Patient patient = new Patient();
|
||||
|
@ -95,6 +120,21 @@ public class GenericClientExample {
|
|||
System.out.println("Got ID: " + id.getValue());
|
||||
// END SNIPPET: update
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
// START SNIPPET: updateConditional
|
||||
client.update()
|
||||
.resource(patient)
|
||||
.conditionalByUrl("Patient?identifier=system%7C00001")
|
||||
.execute();
|
||||
|
||||
client.update()
|
||||
.resource(patient)
|
||||
.conditional()
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||
.execute();
|
||||
// END SNIPPET: updateConditional
|
||||
}
|
||||
{
|
||||
// START SNIPPET: etagupdate
|
||||
// First, let's retrive the latest version of a resource
|
||||
|
@ -132,16 +172,27 @@ public class GenericClientExample {
|
|||
}
|
||||
{
|
||||
// START SNIPPET: delete
|
||||
// Retrieve the server's conformance statement and print its
|
||||
// description
|
||||
BaseOperationOutcome outcome = client.delete().resourceById(new IdDt("Patient", "1234")).execute();
|
||||
BaseOperationOutcome resp = client.delete().resourceById(new IdDt("Patient", "1234")).execute();
|
||||
|
||||
// outcome may be null if the server didn't return one
|
||||
if (outcome != null) {
|
||||
if (resp != null) {
|
||||
OperationOutcome outcome = (OperationOutcome) resp;
|
||||
System.out.println(outcome.getIssueFirstRep().getDetailsElement().getValue());
|
||||
}
|
||||
// END SNIPPET: delete
|
||||
}
|
||||
{
|
||||
// START SNIPPET: deleteConditional
|
||||
client.delete()
|
||||
.resourceConditionalByUrl("Patient?identifier=system%7C00001")
|
||||
.execute();
|
||||
|
||||
client.delete()
|
||||
.resourceConditionalByType("Patient")
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||
.execute();
|
||||
// END SNIPPET: deleteConditional
|
||||
}
|
||||
{
|
||||
// START SNIPPET: search
|
||||
Bundle response = client.search()
|
||||
|
|
|
@ -12,6 +12,7 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
|
|||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
|
||||
@SuppressWarnings("null")
|
||||
//START SNIPPET: provider
|
||||
public class PagingPatientProvider implements IResourceProvider {
|
||||
|
||||
|
@ -21,8 +22,19 @@ public class PagingPatientProvider implements IResourceProvider {
|
|||
@Search
|
||||
public IBundleProvider search(@RequiredParam(name = Patient.SP_FAMILY) StringParam theFamily) {
|
||||
final InstantDt searchTime = InstantDt.withCurrentTime();
|
||||
final List<String> matchingResourceIds = findIdsByFamily(theFamily);
|
||||
|
||||
/*
|
||||
* First, we'll search the database for a set of database row IDs that
|
||||
* match the given search criteria. That way we can keep just the
|
||||
* row IDs around, and load the actual resources on demand later
|
||||
* as the client pages through them.
|
||||
*/
|
||||
final List<Long> matchingResourceIds = null; // <-- implement this
|
||||
|
||||
/*
|
||||
* Return a bundle provider which can page through the IDs and
|
||||
* return the resources that go with them.
|
||||
*/
|
||||
return new IBundleProvider() {
|
||||
|
||||
@Override
|
||||
|
@ -33,7 +45,7 @@ public class PagingPatientProvider implements IResourceProvider {
|
|||
@Override
|
||||
public List<IResource> getResources(int theFromIndex, int theToIndex) {
|
||||
int end = Math.max(theToIndex, matchingResourceIds.size() - 1);
|
||||
List<String> idsToReturn = matchingResourceIds.subList(theFromIndex, end);
|
||||
List<Long> idsToReturn = matchingResourceIds.subList(theFromIndex, end);
|
||||
return loadResourcesByIds(idsToReturn);
|
||||
}
|
||||
|
||||
|
@ -44,18 +56,10 @@ public class PagingPatientProvider implements IResourceProvider {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of resource IDs which match a given family name
|
||||
*/
|
||||
private List<String> findIdsByFamily(StringParam theFamily) {
|
||||
// .. implement this search against the database ..
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of patient resources given their IDs
|
||||
*/
|
||||
private List<IResource> loadResourcesByIds(List<String> theFamily) {
|
||||
private List<IResource> loadResourcesByIds(List<Long> theIdsToReturn) {
|
||||
// .. implement this search against the database ..
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.AddTags;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalOperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.DeleteTags;
|
||||
|
@ -324,6 +325,23 @@ public void deletePatient(@IdParam IdDt theId) {
|
|||
//END SNIPPET: delete
|
||||
|
||||
|
||||
//START SNIPPET: deleteConditional
|
||||
@Read()
|
||||
public void deletePatientConditional(@IdParam IdDt theId, @ConditionalOperationParam String theConditionalUrl) {
|
||||
// Only one of theId or theConditionalUrl will have a value depending
|
||||
// on whether the URL receieved was a logical ID, or a conditional
|
||||
// search string
|
||||
if (theId != null) {
|
||||
// do a normal delete
|
||||
} else {
|
||||
// do a conditional delete
|
||||
}
|
||||
|
||||
// otherwise, delete was successful
|
||||
return; // can also return MethodOutcome
|
||||
}
|
||||
//END SNIPPET: deleteConditional
|
||||
|
||||
//START SNIPPET: history
|
||||
@History()
|
||||
public List<Patient> getPatientHistory(@IdParam IdDt theId) {
|
||||
|
@ -681,6 +699,25 @@ public MethodOutcome createPatient(@ResourceParam Patient thePatient) {
|
|||
public abstract MethodOutcome createNewPatient(@ResourceParam Patient thePatient);
|
||||
//END SNIPPET: createClient
|
||||
|
||||
//START SNIPPET: updateConditional
|
||||
@Update
|
||||
public MethodOutcome updatePatientConditional(
|
||||
@ResourceParam Patient thePatient,
|
||||
@IdParam IdDt theId,
|
||||
@ConditionalOperationParam String theConditional) {
|
||||
|
||||
// Only one of theId or theConditional will have a value and the other will be null,
|
||||
// depending on the URL passed into the server.
|
||||
if (theConditional != null) {
|
||||
// Do a conditional update. theConditional will have a value like "Patient?identifier=system%7C00001"
|
||||
} else {
|
||||
// Do a normal update. theId will have the identity of the resource to update
|
||||
}
|
||||
|
||||
return new MethodOutcome(); // populate this
|
||||
}
|
||||
//END SNIPPET: updateConditional
|
||||
|
||||
//START SNIPPET: update
|
||||
@Update
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
|
|
|
@ -195,69 +195,6 @@
|
|||
</plugins>
|
||||
</reporting>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>ANDROID</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>0.9-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-android</artifactId>
|
||||
<version>${slf4j_version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<!--
|
||||
<include>javax.json:javax.json-api</include>
|
||||
-->
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<include>org.slf4j:slf4j*</include>
|
||||
<include>org.apache.commons:*</include>
|
||||
<include>org.apache.httpcomponents:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.context;
|
|||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -28,7 +29,6 @@ import java.util.Set;
|
|||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
||||
import ca.uhn.fhir.model.api.ICodeEnum;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
||||
|
@ -41,7 +41,7 @@ public abstract class BaseRuntimeChildDatatypeDefinition extends BaseRuntimeDecl
|
|||
|
||||
public BaseRuntimeChildDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype) {
|
||||
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
|
||||
assert theDatatype != IDatatype.class; // should use RuntimeChildAny
|
||||
assert Modifier.isInterface(theDatatype.getModifiers()) == false : "Type of " + theDatatype + " shouldn't be here"; // should use RuntimeChildAny
|
||||
myDatatype = theDatatype;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@ public abstract class BaseRuntimeElementCompositeDefinition<T extends IBase> ext
|
|||
if (theNext == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
// if (theNext.getValidChildNames().contains("performetPractitioner")) {
|
||||
// throw new NullPointerException();
|
||||
// }
|
||||
if (theNext.getExtensionUrl() != null) {
|
||||
throw new IllegalArgumentException("Shouldn't haven an extension URL, use addExtension instead");
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
|
||||
|
||||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
|
||||
|
@ -102,8 +103,10 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
|
|||
try {
|
||||
if (theArgument == null) {
|
||||
return getImplementingClass().newInstance();
|
||||
} else {
|
||||
} else if (theArgument instanceof IValueSetEnumBinder) {
|
||||
return getImplementingClass().getConstructor(IValueSetEnumBinder.class).newInstance(theArgument);
|
||||
} else {
|
||||
return getImplementingClass().getConstructor(IBaseEnumFactory.class).newInstance(theArgument);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigurationException("Failed to instantiate type:" + getImplementingClass().getName(), e);
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
@ -72,6 +73,7 @@ import ca.uhn.fhir.validation.FhirValidator;
|
|||
public class FhirContext {
|
||||
|
||||
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 volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
||||
|
@ -81,6 +83,7 @@ public class FhirContext {
|
|||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||
private final IFhirVersion myVersion;
|
||||
|
||||
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
||||
|
||||
/**
|
||||
|
@ -123,7 +126,9 @@ public class FhirContext {
|
|||
} else {
|
||||
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructures"));
|
||||
}
|
||||
|
||||
|
||||
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
|
||||
|
||||
scanResourceTypes(toElementList(theResourceTypes));
|
||||
}
|
||||
|
||||
|
@ -176,7 +181,7 @@ public class FhirContext {
|
|||
if (Modifier.isAbstract(theResourceType.getModifiers())) {
|
||||
throw new IllegalArgumentException("Can not scan abstract or interface class (resource definitions must be concrete classes): " + theResourceType.getName());
|
||||
}
|
||||
|
||||
|
||||
RuntimeResourceDefinition retVal = (RuntimeResourceDefinition) myClassToElementDefinition.get(theResourceType);
|
||||
if (retVal == null) {
|
||||
retVal = scanResourceType((Class<? extends IResource>) theResourceType);
|
||||
|
@ -186,7 +191,7 @@ public class FhirContext {
|
|||
|
||||
public RuntimeResourceDefinition getResourceDefinition(FhirVersionEnum theVersion, String theResourceName) {
|
||||
Validate.notNull(theVersion, "theVersion can not be null");
|
||||
|
||||
|
||||
if (theVersion.equals(myVersion.getVersion())) {
|
||||
return getResourceDefinition(theResourceName);
|
||||
}
|
||||
|
@ -195,18 +200,18 @@ public class FhirContext {
|
|||
if (nameToType == null) {
|
||||
nameToType = new HashMap<String, Class<? extends IBaseResource>>();
|
||||
ModelScanner.scanVersionPropertyFile(null, nameToType, theVersion);
|
||||
|
||||
Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> newVersionToNameToResourceType = new HashMap<FhirVersionEnum, Map<String,Class<? extends IBaseResource>>>();
|
||||
|
||||
Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> newVersionToNameToResourceType = new HashMap<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>>();
|
||||
newVersionToNameToResourceType.putAll(myVersionToNameToResourceType);
|
||||
newVersionToNameToResourceType.put(theVersion, nameToType);
|
||||
myVersionToNameToResourceType = newVersionToNameToResourceType;
|
||||
}
|
||||
|
||||
|
||||
Class<? extends IBaseResource> resourceType = nameToType.get(theResourceName.toLowerCase());
|
||||
if (resourceType==null) {
|
||||
if (resourceType == null) {
|
||||
throw new DataFormatException(createUnknownResourceNameError(theResourceName, theVersion));
|
||||
}
|
||||
|
||||
|
||||
return getResourceDefinition(resourceType);
|
||||
}
|
||||
|
||||
|
@ -457,6 +462,10 @@ public class FhirContext {
|
|||
return new FhirContext(FhirVersionEnum.DSTU2);
|
||||
}
|
||||
|
||||
public static FhirContext forDstu2Hl7Org() {
|
||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||
}
|
||||
|
||||
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
retVal.add(theResourceType);
|
||||
|
@ -475,8 +484,4 @@ public class FhirContext {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static FhirContext forDstu2Hl7Org() {
|
||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.context;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -55,6 +55,7 @@ import org.hl7.fhir.instance.model.IPrimitiveType;
|
|||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBackboneElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IDatatypeElement;
|
||||
import org.hl7.fhir.instance.model.api.IDomainResource;
|
||||
|
@ -65,7 +66,6 @@ import ca.uhn.fhir.model.api.CodeableConceptElement;
|
|||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IBoundCodeableConcept;
|
||||
import ca.uhn.fhir.model.api.ICodeEnum;
|
||||
import ca.uhn.fhir.model.api.ICompositeElement;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
|
@ -216,7 +216,7 @@ class ModelScanner {
|
|||
|
||||
long time = System.currentTimeMillis() - start;
|
||||
int size = myClassToElementDefinitions.size() - startSize;
|
||||
ourLog.info("Done scanning FHIR library, found {} model entries in {}ms", size, time);
|
||||
ourLog.debug("Done scanning FHIR library, found {} model entries in {}ms", size, time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,7 +321,7 @@ class ModelScanner {
|
|||
}
|
||||
|
||||
private void scanCompositeDatatype(Class<? extends ICompositeType> theClass, DatatypeDef theDatatypeDefinition) {
|
||||
ourLog.debug("Scanning resource class: {}", theClass.getName());
|
||||
ourLog.debug("Scanning datatype class: {}", theClass.getName());
|
||||
|
||||
RuntimeCompositeDatatypeDefinition resourceDef;
|
||||
if (theClass.equals(ExtensionDt.class)) {
|
||||
|
@ -556,7 +556,7 @@ class ModelScanner {
|
|||
RuntimeChildResourceBlockDefinition def = new RuntimeChildResourceBlockDefinition(next, childAnnotation, descriptionAnnotation, elementName, blockDef);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "org.hl7.fhir.instance.model.Type".equals(nextElementType.getName())) {
|
||||
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "org.hl7.fhir.instance.model.Type".equals(nextElementType.getName()) || IBaseDatatype.class.equals(nextElementType)) {
|
||||
|
||||
RuntimeChildAny def = new RuntimeChildAny(next, elementName, childAnnotation, descriptionAnnotation);
|
||||
orderMap.put(order, def);
|
||||
|
@ -566,10 +566,13 @@ class ModelScanner {
|
|||
|
||||
addScanAlso(nextDatatype);
|
||||
BaseRuntimeChildDatatypeDefinition def;
|
||||
if (IPrimitiveDatatype.class.isAssignableFrom(nextElementType)) {
|
||||
if (IPrimitiveType.class.isAssignableFrom(nextElementType)) {
|
||||
if (nextElementType.equals(BoundCodeDt.class)) {
|
||||
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
|
||||
def = new RuntimeChildPrimitiveBoundCodeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder);
|
||||
} else if (childAnnotation.enumFactory().getSimpleName().equals("NoEnumFactory") == false) {
|
||||
Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory();
|
||||
def = new RuntimeChildEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, enumFactory);
|
||||
} else {
|
||||
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.lang.reflect.Field;
|
||||
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
||||
public class RuntimeChildEnumerationDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
|
||||
|
||||
private Class<? extends IBaseEnumFactory<?>> myBinderType;
|
||||
private volatile IBaseEnumFactory<?> myBinder;
|
||||
|
||||
public RuntimeChildEnumerationDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype, Class<? extends IBaseEnumFactory<?>> theBinderType) {
|
||||
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
|
||||
|
||||
myBinderType = theBinderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseEnumFactory<?> getInstanceConstructorArguments() {
|
||||
IBaseEnumFactory<?> retVal = myBinder;
|
||||
if (retVal == null) {
|
||||
try {
|
||||
retVal = myBinderType.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
|
||||
}
|
||||
myBinder = retVal;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,4 +33,5 @@ public class RuntimeChildPrimitiveDatatypeDefinition extends BaseRuntimeChildDat
|
|||
super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation, theDatatype);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
public class RuntimeElementDirectResource extends BaseRuntimeElementDefinition<IBaseResource> {
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
||||
public abstract class BaseElement implements IElement, ISupportsUndeclaredExtensions {
|
||||
|
||||
|
@ -32,7 +33,7 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
|
|||
private List<ExtensionDt> myUndeclaredModifierExtensions;
|
||||
|
||||
@Override
|
||||
public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IDatatype theValue) {
|
||||
public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
|
||||
Validate.notEmpty(theUrl, "URL must be populated");
|
||||
Validate.notNull(theValue, "Value must not be null");
|
||||
ExtensionDt retVal = new ExtensionDt(theIsModifier, theUrl, theValue);
|
||||
|
|
|
@ -24,21 +24,23 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
||||
@DatatypeDef(name="Extension")
|
||||
public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDatatype {
|
||||
@DatatypeDef(name = "Extension")
|
||||
public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDatatype, IBaseExtension<ExtensionDt> {
|
||||
|
||||
private boolean myModifier;
|
||||
|
||||
@Child(name="url", type=StringDt.class, order=0, min=1, max=1)
|
||||
private StringDt myUrl;
|
||||
|
||||
@Child(name="value", type=IDatatype.class, order=1, min=0, max=1)
|
||||
private IElement myValue;
|
||||
@Child(name = "value", type = IDatatype.class, order = 1, min = 0, max = 1)
|
||||
private IBaseDatatype myValue;
|
||||
|
||||
public ExtensionDt() {
|
||||
}
|
||||
|
@ -54,7 +56,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
myUrl = new StringDt(theUrl);
|
||||
}
|
||||
|
||||
public ExtensionDt(boolean theIsModifier, String theUrl, IDatatype theValue) {
|
||||
public ExtensionDt(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
|
||||
Validate.notEmpty(theUrl, "URL must be populated");
|
||||
Validate.notNull(theValue, "Value must not be null");
|
||||
|
||||
|
@ -63,15 +65,25 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
myValue=theValue;
|
||||
}
|
||||
|
||||
public StringDt getUrl() {
|
||||
if (myUrl==null) {
|
||||
myUrl=new StringDt();
|
||||
}
|
||||
return myUrl;
|
||||
/**
|
||||
* Returns the URL for this extension.
|
||||
* <p>
|
||||
* Note that before HAPI 0.9 this method returned a {@link StringDt} but as of
|
||||
* HAPI 0.9 this method returns a plain string. This was changed because it does not make sense to use a StringDt here
|
||||
* since the URL itself can not contain extensions and it was therefore misleading.
|
||||
* </p>
|
||||
*/
|
||||
public String getUrl() {
|
||||
return myUrl != null ? myUrl.getValue() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retained for backward compatibility
|
||||
*
|
||||
* @see ExtensionDt#getUrl()
|
||||
*/
|
||||
public String getUrlAsString() {
|
||||
return getUrl().getValue();
|
||||
return getUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +93,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
* {@link #getUndeclaredModifierExtensions()} to retrieve the child extensions.
|
||||
* </p>
|
||||
*/
|
||||
public IElement getValue() {
|
||||
public IBaseDatatype getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
|
@ -117,7 +129,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
}
|
||||
|
||||
public ExtensionDt setUrl(String theUrl) {
|
||||
myUrl = new StringDt(theUrl);
|
||||
myUrl = theUrl != null ? new StringDt(theUrl) : myUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -126,8 +138,9 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
return this;
|
||||
}
|
||||
|
||||
public void setValue(IElement theValue) {
|
||||
public ExtensionDt setValue(IBaseDatatype theValue) {
|
||||
myValue = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,4 +148,9 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
|
|||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ExtensionDt> getExtension() {
|
||||
return getAllUndeclaredExtensions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -20,6 +22,6 @@ package ca.uhn.fhir.model.api;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
public interface IDatatype extends IElement {
|
||||
public interface IDatatype extends IElement, IBaseDatatype {
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.hl7.fhir.instance.model.IBaseResource;
|
|||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
@ -49,4 +50,7 @@ public interface IFhirVersion {
|
|||
|
||||
Class<?> getContainedType();
|
||||
|
||||
BaseCodingDt newCodingDt();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ package ca.uhn.fhir.model.api;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
||||
public interface ISupportsUndeclaredExtensions extends IElement {
|
||||
|
||||
/**
|
||||
|
@ -52,7 +54,7 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
|||
* <li>{@link ExtensionDt#setUrl(String) URL}</li>
|
||||
* <li>And one of:
|
||||
* <ul>
|
||||
* <li>{@link ExtensionDt#setValue(IElement) A datatype value}</li>
|
||||
* <li>{@link ExtensionDt#setValue(IBaseDatatype) A datatype value}</li>
|
||||
* <li>{@link #addUndeclaredExtension(ExtensionDt) Further sub-extensions}</li>
|
||||
* </ul>
|
||||
* </ul>
|
||||
|
@ -64,7 +66,7 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
|||
/**
|
||||
* Adds an extension to this object
|
||||
*/
|
||||
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IDatatype theValue);
|
||||
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue);
|
||||
|
||||
/**
|
||||
* Adds an extension to this object. This method is intended for use when
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
|
@ -62,6 +63,36 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
*/
|
||||
public abstract class ResourceMetadataKeyEnum<T> {
|
||||
|
||||
public static final ResourceMetadataKeyEnum<List<BaseCodingDt>> SECURITY_LABELS = new ResourceMetadataKeyEnum<List<BaseCodingDt>>("SECURITY_LABELS") {
|
||||
@Override
|
||||
public List<BaseCodingDt> get(IResource resource) {
|
||||
Object obj = resource.getResourceMetadata().get(SECURITY_LABELS);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) obj;
|
||||
if (securityLabels.isEmpty())
|
||||
return null;
|
||||
else
|
||||
return securityLabels;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InternalErrorException("Found an object of type '" + obj.getClass().getCanonicalName() + "' in resource metadata for key SECURITY_LABELS - Expected "
|
||||
+ BaseCodingDt.class.getCanonicalName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(IResource iResource, List<BaseCodingDt> labels) {
|
||||
iResource.getResourceMetadata().put(SECURITY_LABELS, labels);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* If present and populated with a date/time (as an instance of {@link InstantDt}), this value is an indication that the resource is in the deleted state. This key is only used in a limited number
|
||||
* of scenarios, such as POSTing transaction bundles to a server, or returning resource history.
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
||||
/**
|
||||
* A collection of tags present on a single resource. TagList is backed by a {@link LinkedHashSet}, so the order of added tags will be consistent, but duplicates will not be preserved.
|
||||
*
|
||||
|
@ -35,7 +37,7 @@ import java.util.Set;
|
|||
* <b>Thread safety:</b> This class is not thread safe
|
||||
* </p>
|
||||
*/
|
||||
public class TagList implements Set<Tag>, Serializable {
|
||||
public class TagList implements Set<Tag>, Serializable, IBase {
|
||||
|
||||
public static final String ATTR_CATEGORY = "category";
|
||||
public static final String ELEMENT_NAME = "TagList";
|
||||
|
|
|
@ -24,6 +24,9 @@ import java.lang.annotation.ElementType;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
|
||||
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
|
||||
|
@ -96,5 +99,29 @@ public @interface Child {
|
|||
// * HumanNameDt which adds extensions of your choosing) you could do that using a replacement field.
|
||||
// */
|
||||
// String replaces() default "";
|
||||
|
||||
|
||||
/**
|
||||
* For children which accept an {@link Enumeration} as the type, this
|
||||
* field indicates the type to use for the enum factory
|
||||
*/
|
||||
Class<? extends IBaseEnumFactory<?>> enumFactory() default NoEnumFactory.class;
|
||||
|
||||
public static class NoEnumFactory implements IBaseEnumFactory<Enum<?>> {
|
||||
|
||||
private NoEnumFactory() {
|
||||
// non instantiable
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum<?> fromCode(String theCodeString) throws IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toCode(Enum<?> theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
@Target(value=ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SearchParamDefinition {
|
||||
|
@ -57,5 +59,11 @@ public @interface SearchParamDefinition {
|
|||
* </p>
|
||||
*/
|
||||
String[] compositeOf() default {};
|
||||
|
||||
/**
|
||||
* For search params of type "reference", this can optionally be used to
|
||||
* specify the resource type(s) that this parameter applies to.
|
||||
*/
|
||||
Class<? extends IBaseResource>[] target() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -65,10 +65,17 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
|
|||
* A representation of the meaning of the code in the system, following the rules of the system.
|
||||
* </p>
|
||||
*/
|
||||
public abstract StringDt getDisplayElement();
|
||||
|
||||
public abstract StringDt getDisplayElement();
|
||||
|
||||
public abstract BaseCodingDt setDisplay( String theString);
|
||||
|
||||
/*
|
||||
todo: handle version
|
||||
public abstract StringDt getVersion();
|
||||
|
||||
public abstract BaseCodingDt setVersion ( String theString);
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -22,14 +22,12 @@ package ca.uhn.fhir.model.base.composite;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
|
||||
import javax.json.JsonValue;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
|
||||
|
@ -40,7 +38,7 @@ import ca.uhn.fhir.parser.IParser;
|
|||
import ca.uhn.fhir.rest.client.BaseClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
|
||||
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement {
|
||||
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement implements IBaseDatatype {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
|
||||
private IResource myResource;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.model.base.resource;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
public interface BaseBinary extends IResource {
|
||||
|
|
|
@ -118,6 +118,18 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
|
|||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theIdPart
|
||||
* The ID (e.g. "123")
|
||||
*/
|
||||
public IdDt(String theResourceType, Long theIdPart) {
|
||||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theId
|
||||
* The ID (e.g. "123")
|
||||
*/
|
||||
|
@ -515,6 +527,13 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
|
|||
return theIdPart.toPlainString();
|
||||
}
|
||||
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(Long theIdPart) {
|
||||
if (theIdPart == null) {
|
||||
throw new NullPointerException("Long ID can not be null");
|
||||
}
|
||||
return theIdPart.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isBlank(getValue());
|
||||
|
|
|
@ -20,7 +20,9 @@ package ca.uhn.fhir.parser;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -47,6 +49,8 @@ import javax.json.stream.JsonGenerator;
|
|||
import javax.json.stream.JsonGeneratorFactory;
|
||||
import javax.json.stream.JsonParsingException;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.primitive.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
@ -54,7 +58,11 @@ import org.hl7.fhir.instance.model.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
|
@ -85,7 +93,6 @@ import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
|||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.base.resource.BaseBinary;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
|
@ -127,7 +134,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
private void addToHeldExtensions(int valueIdx, List<ExtensionDt> ext, ArrayList<ArrayList<HeldExtension>> list) {
|
||||
private void addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier) {
|
||||
if (ext.size() > 0) {
|
||||
list.ensureCapacity(valueIdx);
|
||||
while (list.size() <= valueIdx) {
|
||||
|
@ -136,8 +143,8 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (list.get(valueIdx) == null) {
|
||||
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
||||
}
|
||||
for (ExtensionDt next : ext) {
|
||||
list.get(valueIdx).add(new HeldExtension(next));
|
||||
for (IBaseExtension<?> next : ext) {
|
||||
list.get(valueIdx).add(new HeldExtension(next, theIsModifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +290,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource);
|
||||
encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "resource", false);
|
||||
}
|
||||
|
||||
|
||||
if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
|
||||
theEventWriter.writeStartObject("search");
|
||||
writeOptionalTagWithTextNode(theEventWriter, "mode", nextEntry.getSearchMode().getValueAsString());
|
||||
|
@ -325,7 +332,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
//
|
||||
// writeAuthor(nextEntry, theEventWriter);
|
||||
|
||||
|
||||
if (nextEntry.getSummary().isEmpty() == false) {
|
||||
theEventWriter.write("summary", nextEntry.getSummary().getValueAsString());
|
||||
}
|
||||
|
@ -411,8 +417,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
case CONTAINED_RESOURCES: {
|
||||
/*
|
||||
* Disabled per #103
|
||||
* ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) {
|
||||
* Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) {
|
||||
* continue; } encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(next.getId().getValue())); }
|
||||
*/
|
||||
List<IBaseResource> containedResources = getContainedResources().getContainedResources();
|
||||
|
@ -460,11 +465,15 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
|
||||
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
|
||||
for (BaseRuntimeChildDefinition nextChild : theChildren) {
|
||||
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
if (gen != null) {
|
||||
BaseNarrativeDt<?> narr = ((IResource)theResource).getText();
|
||||
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
|
||||
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
|
||||
if (narr != null) {
|
||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||
|
@ -540,12 +549,25 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource);
|
||||
}
|
||||
|
||||
if (nextValue instanceof ISupportsUndeclaredExtensions && primitive) {
|
||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, extensions);
|
||||
if (primitive) {
|
||||
if (nextValue instanceof ISupportsUndeclaredExtensions) {
|
||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
|
||||
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, modifierExtensions);
|
||||
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, modifierExtensions, true);
|
||||
} else {
|
||||
if (nextValue instanceof IBaseHasExtensions) {
|
||||
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?>> ext = element.getExtension();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
}
|
||||
if (nextValue instanceof IBaseHasModifierExtensions) {
|
||||
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?>> ext = element.getModifierExtension();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -648,11 +670,26 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) {
|
||||
IResource resource = (IResource) theResource;
|
||||
if (!ElementUtil.isEmpty(resource.getId().getVersionIdPart(), ResourceMetadataKeyEnum.UPDATED.get(resource))) {
|
||||
List<BaseCodingDt> securityLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(resource);
|
||||
if (securityLabels == null) {
|
||||
securityLabels = Collections.emptyList();
|
||||
}
|
||||
if (!ElementUtil.isEmpty(resource.getId().getVersionIdPart(), ResourceMetadataKeyEnum.UPDATED.get(resource), securityLabels)) {
|
||||
theEventWriter.writeStartObject("meta");
|
||||
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart());
|
||||
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource));
|
||||
theEventWriter.writeEnd();
|
||||
|
||||
if (securityLabels.isEmpty()==false) {
|
||||
theEventWriter.writeStartArray("security");
|
||||
for (BaseCodingDt securityLabel : securityLabels) {
|
||||
theEventWriter.writeStartObject();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theIsSubElementWithinResource);
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
theEventWriter.writeEnd(); //end meta
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +700,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
} else {
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource);
|
||||
}
|
||||
|
||||
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
|
@ -751,22 +788,44 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void extractUndeclaredExtensions(IBase theResource, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
||||
if (theResource instanceof ISupportsUndeclaredExtensions) {
|
||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) theResource).getUndeclaredExtensions();
|
||||
private void extractUndeclaredExtensions(IBase theElement, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions element = (ISupportsUndeclaredExtensions) theElement;
|
||||
List<ExtensionDt> ext = element.getUndeclaredExtensions();
|
||||
for (ExtensionDt next : ext) {
|
||||
if (next == null || next.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
extensions.add(new HeldExtension(next));
|
||||
extensions.add(new HeldExtension(next, false));
|
||||
}
|
||||
|
||||
ext = ((ISupportsUndeclaredExtensions) theResource).getUndeclaredModifierExtensions();
|
||||
ext = element.getUndeclaredModifierExtensions();
|
||||
for (ExtensionDt next : ext) {
|
||||
if (next == null || next.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
modifierExtensions.add(new HeldExtension(next));
|
||||
modifierExtensions.add(new HeldExtension(next, true));
|
||||
}
|
||||
} else {
|
||||
if (theElement instanceof IBaseHasExtensions) {
|
||||
IBaseHasExtensions element = (IBaseHasExtensions) theElement;
|
||||
List<? extends IBaseExtension<?>> ext = element.getExtension();
|
||||
for (IBaseExtension<?> next : ext) {
|
||||
if (next == null || next.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
extensions.add(new HeldExtension(next, false));
|
||||
}
|
||||
}
|
||||
if (theElement instanceof IBaseHasModifierExtensions) {
|
||||
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) theElement;
|
||||
List<? extends IBaseExtension<?>> ext = element.getModifierExtension();
|
||||
for (IBaseExtension<?> next : ext) {
|
||||
if (next == null || next.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
modifierExtensions.add(new HeldExtension(next, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -788,16 +847,15 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
return;
|
||||
}
|
||||
|
||||
boolean newerThanDstu1 = myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1);
|
||||
JsonObject alternate = (JsonObject) theAlternateVal;
|
||||
for (Entry<String, JsonValue> nextEntry : alternate.entrySet()) {
|
||||
String nextKey = nextEntry.getKey();
|
||||
JsonValue nextVal = nextEntry.getValue();
|
||||
if (!newerThanDstu1 && "extension".equals(nextKey)) {
|
||||
if ("extension".equals(nextKey)) {
|
||||
boolean isModifier = false;
|
||||
JsonArray array = (JsonArray) nextEntry.getValue();
|
||||
parseExtension(theState, array, isModifier);
|
||||
} else if (!newerThanDstu1 && "modifierExtension".equals(nextKey)) {
|
||||
} else if ("modifierExtension".equals(nextKey)) {
|
||||
boolean isModifier = true;
|
||||
JsonArray array = (JsonArray) nextEntry.getValue();
|
||||
parseExtension(theState, array, isModifier);
|
||||
|
@ -811,12 +869,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (newerThanDstu1) {
|
||||
if (nextKey.indexOf(':') > -1 && newerThanDstu1) {
|
||||
JsonArray array = (JsonArray) nextEntry.getValue();
|
||||
parseExtensionInDstu2Style(false, theState, null, nextKey, array);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -935,7 +987,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
private void parseChildren(JsonObject theObject, ParserState<?> theState) {
|
||||
String elementId = null;
|
||||
boolean newerThanDstu1 = myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1);
|
||||
for (String nextName : theObject.keySet()) {
|
||||
if ("resourceType".equals(nextName)) {
|
||||
continue;
|
||||
|
@ -948,29 +999,16 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
// _id is incorrect, but some early examples in the FHIR spec used it
|
||||
elementId = theObject.getString(nextName);
|
||||
continue;
|
||||
} else if (!newerThanDstu1 && "extension".equals(nextName)) {
|
||||
} else if ("extension".equals(nextName)) {
|
||||
JsonArray array = theObject.getJsonArray(nextName);
|
||||
parseExtension(theState, array, false);
|
||||
continue;
|
||||
} else if (!newerThanDstu1 && "modifierExtension".equals(nextName)) {
|
||||
} else if ("modifierExtension".equals(nextName)) {
|
||||
JsonArray array = theObject.getJsonArray(nextName);
|
||||
parseExtension(theState, array, true);
|
||||
continue;
|
||||
} else if (newerThanDstu1 && "modifier".equals(nextName)) {
|
||||
JsonObject obj = theObject.getJsonObject(nextName);
|
||||
for (String nextUrl : obj.keySet()) {
|
||||
JsonArray array = obj.getJsonArray(nextUrl);
|
||||
parseExtensionInDstu2Style(true, theState, null, nextUrl, array);
|
||||
}
|
||||
continue;
|
||||
} else if (nextName.charAt(0) == '_') {
|
||||
continue;
|
||||
} else {
|
||||
if (newerThanDstu1 && nextName.indexOf(':') > -1) {
|
||||
JsonArray array = theObject.getJsonArray(nextName);
|
||||
parseExtensionInDstu2Style(false, theState, null, nextName, array);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
JsonValue nextVal = theObject.get(nextName);
|
||||
|
@ -1210,42 +1248,18 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
||||
List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
|
||||
if (extensions.isEmpty() == false) {
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
Collections.sort(extensions);
|
||||
String currentlyWritingExtensionUrl = null;
|
||||
for (HeldExtension next : extensions) {
|
||||
currentlyWritingExtensionUrl = next.writeExtensionInDstu2Format(resDef, theResource, theEventWriter, currentlyWritingExtensionUrl, theParentExtensionUrl);
|
||||
}
|
||||
if (currentlyWritingExtensionUrl != null) {
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
} else {
|
||||
theEventWriter.writeStartArray("extension");
|
||||
for (HeldExtension next : extensions) {
|
||||
next.write(resDef, theResource, theEventWriter);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
theEventWriter.writeStartArray("extension");
|
||||
for (HeldExtension next : extensions) {
|
||||
next.write(resDef, theResource, theEventWriter);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
if (modifierExtensions.isEmpty() == false) {
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
Collections.sort(modifierExtensions);
|
||||
theEventWriter.writeStartObject("modifier");
|
||||
String currentlyWritingExtensionUrl = null;
|
||||
for (HeldExtension next : modifierExtensions) {
|
||||
currentlyWritingExtensionUrl = next.writeExtensionInDstu2Format(resDef, theResource, theEventWriter, currentlyWritingExtensionUrl, theParentExtensionUrl);
|
||||
}
|
||||
if (currentlyWritingExtensionUrl != null) {
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
} else {
|
||||
theEventWriter.writeStartArray("modifierExtension");
|
||||
for (HeldExtension next : modifierExtensions) {
|
||||
next.write(resDef, theResource, theEventWriter);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
theEventWriter.writeStartArray("modifierExtension");
|
||||
for (HeldExtension next : modifierExtensions) {
|
||||
next.write(resDef, theResource, theEventWriter);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,14 +1297,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, String theValue) {
|
||||
if (theValue != null && !theValue.isEmpty()) {
|
||||
theEventWriter.write(theElementName, theValue);
|
||||
} else {
|
||||
theEventWriter.writeNull(theElementName);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
theEventWriter.write(theElementName, theStringDt.getValue());
|
||||
|
@ -1303,12 +1309,14 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
private class HeldExtension implements Comparable<HeldExtension> {
|
||||
|
||||
private RuntimeChildDeclaredExtensionDefinition myDef;
|
||||
private ExtensionDt myUndeclaredExtension;
|
||||
private IBaseExtension<?> myUndeclaredExtension;
|
||||
private IBase myValue;
|
||||
private boolean myModifier;
|
||||
|
||||
public HeldExtension(ExtensionDt theUndeclaredExtension) {
|
||||
public HeldExtension(IBaseExtension<?> theUndeclaredExtension, boolean theModifier) {
|
||||
assert theUndeclaredExtension != null;
|
||||
myUndeclaredExtension = theUndeclaredExtension;
|
||||
myModifier = theModifier;
|
||||
}
|
||||
|
||||
public HeldExtension(RuntimeChildDeclaredExtensionDefinition theDef, IBase theValue) {
|
||||
|
@ -1337,66 +1345,38 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
public String writeExtensionInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theCurrentlyWritingExtensionUrl,
|
||||
String theParentExtensionUrl) throws IOException {
|
||||
if (myUndeclaredExtension != null) {
|
||||
return writeUndeclaredExtInDstu2Format(theResDef, theResource, theEventWriter, myUndeclaredExtension, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
|
||||
} else {
|
||||
String extensionUrl = myDef.getExtensionUrl();
|
||||
checkIfNewExtensionUrlArrayIsNeeded(theEventWriter, extensionUrl, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
|
||||
|
||||
theEventWriter.writeStartObject();
|
||||
|
||||
BaseRuntimeElementDefinition<?> def = myDef.getChildElementDefinitionByDatatype(myValue.getClass());
|
||||
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
||||
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, extensionUrl);
|
||||
} else {
|
||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false);
|
||||
}
|
||||
|
||||
theEventWriter.writeEnd();
|
||||
|
||||
return extensionUrl;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfNewExtensionUrlArrayIsNeeded(JsonGenerator theEventWriter, String theExtensionUrl, String theCurrentlyWritingExtensionUrl, String theParentExtensionUrl) {
|
||||
if (StringUtils.equals(theCurrentlyWritingExtensionUrl, theExtensionUrl) == false) {
|
||||
if (isNotBlank(theCurrentlyWritingExtensionUrl)) {
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
String urlToWrite = UrlUtil.constructRelativeUrl(theParentExtensionUrl, theExtensionUrl);
|
||||
theEventWriter.writeStartArray(urlToWrite);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, ExtensionDt ext) throws IOException {
|
||||
IElement value = ext.getValue();
|
||||
String extensionUrl = ext.getUrl().getValue();
|
||||
private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, IBaseExtension<?> ext) throws IOException {
|
||||
IBaseDatatype value = ext.getValue();
|
||||
String extensionUrl = ext.getUrl();
|
||||
|
||||
theEventWriter.writeStartObject();
|
||||
theEventWriter.write("url", extensionUrl);
|
||||
|
||||
boolean noValue = value == null || value.isEmpty();
|
||||
if (noValue && ext.getAllUndeclaredExtensions().isEmpty()) {
|
||||
if (noValue && ext.getExtension().isEmpty()) {
|
||||
ourLog.debug("Extension with URL[{}] has no value", extensionUrl);
|
||||
} else if (noValue) {
|
||||
|
||||
theEventWriter.writeStartArray("extension");
|
||||
if (myModifier) {
|
||||
theEventWriter.writeStartArray("modifierExtension");
|
||||
} else {
|
||||
theEventWriter.writeStartArray("extension");
|
||||
}
|
||||
|
||||
for (ExtensionDt next : ext.getUndeclaredExtensions()) {
|
||||
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, next);
|
||||
for (Object next : ext.getExtension()) {
|
||||
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, (IBaseExtension<?>) next);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
} else {
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||
if (childName == null) {
|
||||
childName = "value" + myContext.getElementDefinition(value.getClass()).getName();
|
||||
}
|
||||
BaseRuntimeElementDefinition<?> childDef = myContext.getElementDefinition(value.getClass());
|
||||
if (childDef == null) {
|
||||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true);
|
||||
}
|
||||
|
||||
|
@ -1405,53 +1385,10 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
private String writeUndeclaredExtInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, ExtensionDt ext,
|
||||
String theCurrentlyWritingExtensionUrl, String theParentExtensionUrl) throws IOException {
|
||||
IElement value = ext.getValue();
|
||||
String extensionUrl = ext.getUrl().getValue();
|
||||
|
||||
checkIfNewExtensionUrlArrayIsNeeded(theEventWriter, extensionUrl, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
|
||||
theEventWriter.writeStartObject();
|
||||
|
||||
boolean noValue = value == null || value.isEmpty();
|
||||
if (noValue && ext.getAllUndeclaredExtensions().isEmpty()) {
|
||||
|
||||
ourLog.debug("Extension with URL[{}] has no value", extensionUrl);
|
||||
|
||||
} else if (noValue) {
|
||||
|
||||
BaseRuntimeElementDefinition<?> elemDef = null;
|
||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||
extractAndWriteExtensionsAsDirectChild(ext, theEventWriter, elemDef, resDef, theResource, extensionUrl);
|
||||
|
||||
} else {
|
||||
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||
BaseRuntimeElementDefinition<?> childDef;
|
||||
if (childName == null) {
|
||||
childDef = myContext.getElementDefinition(value.getClass());
|
||||
if (childDef == null) {
|
||||
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
|
||||
} else {
|
||||
childName = RuntimeChildUndeclaredExtensionDefinition.createExtensionChildName(childDef);
|
||||
}
|
||||
} else {
|
||||
childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true);
|
||||
|
||||
}
|
||||
|
||||
theEventWriter.writeEnd();
|
||||
|
||||
return extensionUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(HeldExtension theArg0) {
|
||||
String url1 = myDef != null ? myDef.getExtensionUrl() : myUndeclaredExtension.getUrlAsString();
|
||||
String url2 = theArg0.myDef != null ? theArg0.myDef.getExtensionUrl() : theArg0.myUndeclaredExtension.getUrlAsString();
|
||||
String url1 = myDef != null ? myDef.getExtensionUrl() : myUndeclaredExtension.getUrl();
|
||||
String url2 = theArg0.myDef != null ? theArg0.myDef.getExtensionUrl() : theArg0.myUndeclaredExtension.getUrl();
|
||||
url1 = defaultString(url1);
|
||||
url2 = defaultString(url2);
|
||||
return url1.compareTo(url2);
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.Map;
|
|||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
@ -37,7 +39,11 @@ import org.hl7.fhir.instance.model.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.ICompositeType;
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IReference;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
|
@ -48,29 +54,25 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeElemContainedResources;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceReferenceDefinition;
|
||||
import ca.uhn.fhir.model.api.BaseBundle;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||
import ca.uhn.fhir.model.api.ICompositeElement;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IExtension;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.api.IIdentifiableElement;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.IResourceBlock;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
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.BaseContainedDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.base.resource.BaseBinary;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
|
@ -819,11 +821,29 @@ class ParserState<T> {
|
|||
ExtensionState newState = new ExtensionState(myPreResourceState, newExtension);
|
||||
push(newState);
|
||||
} else {
|
||||
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
|
||||
if (theIsModifier == false) {
|
||||
if (getCurrentElement() instanceof IBaseHasExtensions) {
|
||||
IBaseExtension<?> ext = ((IBaseHasExtensions) getCurrentElement()).addExtension();
|
||||
ext.setUrl(theUrlAttr);
|
||||
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
||||
push(newState);
|
||||
} else {
|
||||
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
|
||||
}
|
||||
} else {
|
||||
if (getCurrentElement() instanceof IBaseHasModifierExtensions) {
|
||||
IBaseExtension<?> ext = ((IBaseHasModifierExtensions) getCurrentElement()).addModifierExtension();
|
||||
ext.setUrl(theUrlAttr);
|
||||
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
||||
push(newState);
|
||||
} else {
|
||||
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Object getCurrentElement() {
|
||||
protected IBase getCurrentElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -879,7 +899,7 @@ class ParserState<T> {
|
|||
if ("id".equals(theName)) {
|
||||
if (myInstance instanceof IIdentifiableElement) {
|
||||
((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
|
||||
} else if (myInstance instanceof IBaseResource) {
|
||||
} else {
|
||||
(myInstance).setId(new IdDt(theValue));
|
||||
}
|
||||
} else if ("contentType".equals(theName)) {
|
||||
|
@ -1578,16 +1598,16 @@ class ParserState<T> {
|
|||
|
||||
private class ExtensionState extends BaseState {
|
||||
|
||||
private ExtensionDt myExtension;
|
||||
private IBaseExtension<?> myExtension;
|
||||
|
||||
public ExtensionState(PreResourceState thePreResourceState, ExtensionDt theExtension) {
|
||||
public ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?> theExtension) {
|
||||
super(thePreResourceState);
|
||||
myExtension = theExtension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
if (myExtension.getValue() != null && myExtension.getUndeclaredExtensions().size() > 0) {
|
||||
if (myExtension.getValue() != null && myExtension.getExtension().size() > 0) {
|
||||
throw new DataFormatException("Extension must not have both a value and other contained extensions");
|
||||
}
|
||||
pop();
|
||||
|
@ -1612,7 +1632,7 @@ class ParserState<T> {
|
|||
case PRIMITIVE_DATATYPE: {
|
||||
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
|
||||
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance();
|
||||
myExtension.setValue((IElement) newChildInstance);
|
||||
myExtension.setValue(newChildInstance);
|
||||
PrimitiveState newState = new PrimitiveState(getPreResourceState(), newChildInstance);
|
||||
push(newState);
|
||||
return;
|
||||
|
@ -1635,12 +1655,27 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
protected IBaseExtension<?> getCurrentElement() {
|
||||
return myExtension;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class SecurityLabelElementStateHapi extends ElementCompositeState<BaseCodingDt> {
|
||||
|
||||
public SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState,BaseRuntimeElementCompositeDefinition<?> theDef, BaseCodingDt codingDt) {
|
||||
super(thePreResourceState, theDef, codingDt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class MetaElementState extends BaseState {
|
||||
private ResourceMetadataMap myMap;
|
||||
|
||||
|
@ -1664,6 +1699,17 @@ class ParserState<T> {
|
|||
InstantDt updated = new InstantDt();
|
||||
push(new PrimitiveState(getPreResourceState(), updated));
|
||||
myMap.put(ResourceMetadataKeyEnum.UPDATED, updated);
|
||||
} else if (theLocalPart.equals("security")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) myMap.get(ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||
if (securityLabels == null) {
|
||||
securityLabels = new ArrayList<BaseCodingDt>();
|
||||
myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels);
|
||||
}
|
||||
BaseCodingDt securityLabel= myContext.getVersion().newCodingDt();
|
||||
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
|
||||
securityLabels.add(securityLabel);
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element '" + theLocalPart + "' found in 'meta' element");
|
||||
}
|
||||
|
@ -1805,6 +1851,15 @@ class ParserState<T> {
|
|||
super(theResourceType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void wereBack() {
|
||||
super.wereBack();
|
||||
if (myTarget == null) {
|
||||
myObject = (T) getCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
super.enteringNewElement(theNamespaceURI, theLocalPart);
|
||||
|
@ -1896,7 +1951,6 @@ class ParserState<T> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void wereBack() {
|
||||
myContext.newTerser().visit(myInstance, new IModelVisitor() {
|
||||
|
@ -1953,7 +2007,7 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected TagList getCurrentElement() {
|
||||
protected IBase getCurrentElement() {
|
||||
return myTagList;
|
||||
}
|
||||
|
||||
|
@ -2237,6 +2291,11 @@ class ParserState<T> {
|
|||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBase getCurrentElement() {
|
||||
return myTagList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if (TagList.ATTR_CATEGORY.equals(theLocalPart)) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.io.Reader;
|
|||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -47,7 +48,12 @@ import javax.xml.stream.events.XMLEvent;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IDomainResource;
|
||||
import org.hl7.fhir.instance.model.api.INarrative;
|
||||
|
||||
|
@ -64,14 +70,12 @@ import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
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.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
|
@ -81,7 +85,6 @@ import ca.uhn.fhir.model.primitive.InstantDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
|
||||
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
||||
import ca.uhn.fhir.util.XmlUtil;
|
||||
|
@ -171,7 +174,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), true);
|
||||
|
||||
} else {
|
||||
|
||||
String elementName = elem.getName().getLocalPart();
|
||||
|
@ -390,7 +392,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
|
||||
deleted = true;
|
||||
}
|
||||
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "base", determineResourceBaseUrl(bundleBaseUrl, nextEntry));
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
|
@ -433,8 +435,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.close();
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (nextValue.isEmpty()) {
|
||||
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
|
||||
// We still want to go in..
|
||||
|
@ -445,12 +446,12 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
switch (childDef.getChildType()) {
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
IPrimitiveDatatype<?> pd = (IPrimitiveDatatype<?>) nextValue;
|
||||
IPrimitiveType<?> pd = (IPrimitiveType<?>) nextValue;
|
||||
String value = pd.getValueAsString();
|
||||
if (value != null) {
|
||||
theEventWriter.writeStartElement(childName);
|
||||
theEventWriter.writeAttribute("value", value);
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, nextValue, theIncludedResource);
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, nextValue, theIncludedResource);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
break;
|
||||
|
@ -462,7 +463,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeAttribute("url", theExtensionUrl);
|
||||
}
|
||||
BaseRuntimeElementCompositeDefinition<?> childCompositeDef = (BaseRuntimeElementCompositeDefinition<?>) childDef;
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, nextValue, theEventWriter, childCompositeDef, theIncludedResource);
|
||||
encodeCompositeElementToStreamWriter(theResource, nextValue, theEventWriter, childCompositeDef, theIncludedResource);
|
||||
theEventWriter.writeEndElement();
|
||||
break;
|
||||
}
|
||||
|
@ -513,21 +514,25 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException,
|
||||
DataFormatException {
|
||||
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (BaseRuntimeChildDefinition nextChild : children) {
|
||||
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
if (theResource instanceof IResource) {
|
||||
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
|
||||
if (gen != null && narr.isEmpty()) {
|
||||
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
|
||||
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
|
||||
gen.generateNarrative(resourceProfile, theResource, narr);
|
||||
}
|
||||
if (narr.isEmpty()==false) {
|
||||
if (narr.isEmpty() == false) {
|
||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, childName, type, null, theIncludedResource);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theIncludedResource);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
@ -535,13 +540,14 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
BaseNarrativeDt<?> narr2 = null;
|
||||
if (gen != null && narr1.isEmpty()) {
|
||||
// TODO: need to implement this
|
||||
gen.generateNarrative(theResDef.getResourceProfile(), theResource, null);
|
||||
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
|
||||
gen.generateNarrative(resourceProfile, theResource, null);
|
||||
}
|
||||
if (narr2 != null) {
|
||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -564,10 +570,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
super.throwExceptionForUnknownChildType(nextChild, type);
|
||||
}
|
||||
|
||||
if (nextValue instanceof ExtensionDt) {
|
||||
|
||||
extensionUrl = ((ExtensionDt) nextValue).getUrlAsString();
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
||||
if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
// This is called for the Query resource in DSTU1 only
|
||||
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
||||
|
||||
} else if (extensionUrl != null && childName.equals("extension") == false) {
|
||||
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
||||
|
@ -578,29 +584,48 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
theEventWriter.writeAttribute("url", extensionUrl);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
|
||||
theEventWriter.writeEndElement();
|
||||
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) {
|
||||
// suppress narratives from contained resources
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(), theIncludedResource);
|
||||
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
|
||||
}
|
||||
|
||||
private void encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeExtensionsIfPresent(IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredExtensions(), "extension", theIncludedResource);
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension", theIncludedResource);
|
||||
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredExtensions()), "extension", theIncludedResource);
|
||||
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredModifierExtensions()), "modifierExtension", theIncludedResource);
|
||||
}
|
||||
if (theElement instanceof IBaseHasExtensions) {
|
||||
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResource, theWriter, res.getExtension(), "extension", theIncludedResource);
|
||||
}
|
||||
if (theElement instanceof IBaseHasModifierExtensions) {
|
||||
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResource, theWriter, res.getModifierExtension(), "modifierExtension", theIncludedResource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to
|
||||
* java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?>> seems to be rejected by the compiler
|
||||
* some of the time.
|
||||
*/
|
||||
private <Q extends IBaseExtension<?>> List<IBaseExtension<?>> toBaseExtensionList(final List<Q> theList) {
|
||||
List<IBaseExtension<?>> retVal = new ArrayList<IBaseExtension<?>>(theList.size());
|
||||
retVal.addAll(theList);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, BaseResourceReferenceDt theRef) throws XMLStreamException {
|
||||
|
@ -636,12 +661,12 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
postExtensionChildren.add(next);
|
||||
}
|
||||
}
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, preExtensionChildren, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, preExtensionChildren, theIncludedResource);
|
||||
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
|
||||
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, postExtensionChildren, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, postExtensionChildren, theIncludedResource);
|
||||
|
||||
}
|
||||
|
||||
|
@ -701,54 +726,70 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeStartElement(resDef.getName());
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
if (theResource instanceof IAnyResource) {
|
||||
|
||||
// DSTU2+
|
||||
IResource resource = (IResource) theResource;
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
|
||||
|
||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
IdDt resourceId = resource.getId();
|
||||
if (resourceId != null && isNotBlank(resourceId.getVersionIdPart()) || (updated != null && !updated.isEmpty())) {
|
||||
theEventWriter.writeStartElement("meta");
|
||||
String versionIdPart = resourceId.getVersionIdPart();
|
||||
if (isBlank(versionIdPart)) {
|
||||
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
||||
}
|
||||
writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
|
||||
if (updated != null) {
|
||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
// HL7.org Structures
|
||||
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
|
||||
} else {
|
||||
|
||||
// DSTU1
|
||||
if (theResourceId != null && theContainedResource) {
|
||||
theEventWriter.writeAttribute("id", theResourceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (theResource instanceof BaseBinary) {
|
||||
BaseBinary bin = (BaseBinary) theResource;
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
||||
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
||||
} else {
|
||||
if (bin.getContentType() != null) {
|
||||
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
||||
}
|
||||
theEventWriter.writeCharacters(bin.getContentAsBase64());
|
||||
}
|
||||
} else {
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
|
||||
// DSTU2+
|
||||
encodeResourceToStreamWriterInDstu2Format(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
|
||||
IResource resource = (IResource) theResource;
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
|
||||
|
||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
IdDt resourceId = resource.getId();
|
||||
List<BaseCodingDt> securityLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(resource);
|
||||
if (securityLabels == null) {
|
||||
securityLabels = Collections.emptyList();
|
||||
}
|
||||
if ((resourceId != null && isNotBlank(resourceId.getVersionIdPart())) || (updated != null && !updated.isEmpty()) || !securityLabels.isEmpty()) {
|
||||
theEventWriter.writeStartElement("meta");
|
||||
String versionIdPart = resourceId.getVersionIdPart();
|
||||
if (isBlank(versionIdPart)) {
|
||||
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
||||
}
|
||||
writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
|
||||
if (updated != null) {
|
||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||
}
|
||||
for (BaseCodingDt securityLabel : securityLabels) {
|
||||
theEventWriter.writeStartElement("security");
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||
encodeCompositeElementChildrenToStreamWriter(resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
if (theResource instanceof BaseBinary) {
|
||||
BaseBinary bin = (BaseBinary) theResource;
|
||||
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
||||
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
||||
} else {
|
||||
encodeResourceToStreamWriterInDstu2Format(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// DSTU1
|
||||
encodeCompositeElementToStreamWriter(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
if (theResourceId != null && theContainedResource) {
|
||||
theEventWriter.writeAttribute("id", theResourceId);
|
||||
}
|
||||
|
||||
if (theResource instanceof BaseBinary) {
|
||||
BaseBinary bin = (BaseBinary) theResource;
|
||||
if (bin.getContentType() != null) {
|
||||
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
||||
}
|
||||
theEventWriter.writeCharacters(bin.getContentAsBase64());
|
||||
} else {
|
||||
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -787,24 +828,19 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeUndeclaredExtensions(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, List<ExtensionDt> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (ExtensionDt next : theExtensions) {
|
||||
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (IBaseExtension<?> next : theExtensions) {
|
||||
if (next == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
theWriter.writeStartElement(tagName);
|
||||
theWriter.writeAttribute("url", next.getUrl().getValue());
|
||||
|
||||
String url = next.getUrl();
|
||||
theWriter.writeAttribute("url", url);
|
||||
|
||||
if (next.getValue() != null) {
|
||||
IElement value = next.getValue();
|
||||
// RuntimeChildUndeclaredExtensionDefinition extDef =
|
||||
// myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
// String childName = extDef.getChildNameByDatatype(nextValue.getClass());
|
||||
// if (childName == null) {
|
||||
// throw new ConfigurationException("Unable to encode extension, unregognized child element type: " +
|
||||
// nextValue.getClass().getCanonicalName());
|
||||
// }
|
||||
// BaseRuntimeElementDefinition<?> childDef =
|
||||
// extDef.getChildElementDefinitionByDatatype(nextValue.getClass());
|
||||
//
|
||||
//
|
||||
IBaseDatatype value = next.getValue();
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||
BaseRuntimeElementDefinition<?> childDef;
|
||||
|
@ -818,11 +854,11 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
} else {
|
||||
childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theWriter, value, childName, childDef, null, theIncludedResource);
|
||||
encodeChildElementToStreamWriter(theResource, theWriter, value, childName, childDef, null, theIncludedResource);
|
||||
}
|
||||
|
||||
// child extensions
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theWriter, next, theIncludedResource);
|
||||
encodeExtensionsIfPresent(theResource, theWriter, next, theIncludedResource);
|
||||
|
||||
theWriter.writeEndElement();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface ConditionalOperationParam {
|
||||
// just a marker
|
||||
}
|
|
@ -131,6 +131,10 @@ public class MethodOutcome {
|
|||
return myVersionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are
|
||||
* returned to client instances, if the server has responded with an HTTP 201 Created.
|
||||
*/
|
||||
public Boolean getCreated() {
|
||||
return myCreated;
|
||||
}
|
||||
|
@ -146,8 +150,9 @@ public class MethodOutcome {
|
|||
* If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called
|
||||
* whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
|
||||
*/
|
||||
public void setCreated(Boolean theCreated) {
|
||||
public MethodOutcome setCreated(Boolean theCreated) {
|
||||
myCreated = theCreated;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -182,9 +182,14 @@ public abstract class BaseClient {
|
|||
}
|
||||
|
||||
try {
|
||||
ContentType ct = ContentType.get(response.getEntity());
|
||||
String mimeType = ct != null ? ct.getMimeType() : null;
|
||||
|
||||
String mimeType;
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatusLine().getStatusCode()) {
|
||||
mimeType = null;
|
||||
} else {
|
||||
ContentType ct = ContentType.get(response.getEntity());
|
||||
mimeType = ct != null ? ct.getMimeType() : null;
|
||||
}
|
||||
|
||||
Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
if (response.getAllHeaders() != null) {
|
||||
for (Header next : response.getAllHeaders()) {
|
||||
|
@ -398,7 +403,9 @@ public abstract class BaseClient {
|
|||
charset = ct.getCharset();
|
||||
}
|
||||
if (charset == null) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT != theResponse.getStatusLine().getStatusCode()) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
}
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ public abstract class BaseHttpClientInvocation {
|
|||
public abstract HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding);
|
||||
|
||||
protected static void appendExtraParamsWithQuestionMark(Map<String, List<String>> theExtraParams, StringBuilder theUrlBuilder, boolean theWithQuestionMark) {
|
||||
if (theExtraParams == null) {
|
||||
return;
|
||||
}
|
||||
boolean first = theWithQuestionMark;
|
||||
|
||||
if (theExtraParams != null && theExtraParams.isEmpty() == false) {
|
||||
|
|
|
@ -56,10 +56,14 @@ import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
|||
import ca.uhn.fhir.rest.gclient.IClientExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateTyped;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.ICriterion;
|
||||
import ca.uhn.fhir.rest.gclient.ICriterionInternal;
|
||||
import ca.uhn.fhir.rest.gclient.IDelete;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IGetPage;
|
||||
import ca.uhn.fhir.rest.gclient.IGetPageTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IGetTags;
|
||||
|
@ -76,6 +80,8 @@ import ca.uhn.fhir.rest.gclient.IUntypedQuery;
|
|||
import ca.uhn.fhir.rest.gclient.IUpdate;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.method.DeleteMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HistoryMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HttpDeleteClientInvocation;
|
||||
|
@ -237,10 +243,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return new LoadPageInternal();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) {
|
||||
// return doReadOrVRead(theType, theId, false, null, null);
|
||||
// }
|
||||
// @Override
|
||||
// public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) {
|
||||
// return doReadOrVRead(theType, theId, false, null, null);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T read(Class<T> theType, String theId) {
|
||||
|
@ -249,7 +255,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public <T extends IBaseResource> T read(final Class<T> theType, UriDt theUrl) {
|
||||
IdDt id = theUrl instanceof IdDt ? ((IdDt)theUrl) : new IdDt(theUrl);
|
||||
IdDt id = theUrl instanceof IdDt ? ((IdDt) theUrl) : new IdDt(theUrl);
|
||||
return doReadOrVRead(theType, id, false, null, null);
|
||||
}
|
||||
|
||||
|
@ -447,7 +453,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
if (theIfVersionMatches != null) {
|
||||
invocation.addHeader(Constants.HEADER_IF_NONE_MATCH, '"' + theIfVersionMatches + '"');
|
||||
}
|
||||
|
||||
|
||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType, id);
|
||||
|
||||
if (theNotModifiedHandler == null) {
|
||||
|
@ -475,18 +481,18 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return vread(theType, resId);
|
||||
}
|
||||
|
||||
private static void addParam(Map<String, List<String>> params, String parameterName, String parameterValue) {
|
||||
if (!params.containsKey(parameterName)) {
|
||||
params.put(parameterName, new ArrayList<String>());
|
||||
}
|
||||
params.get(parameterName).add(parameterValue);
|
||||
}
|
||||
|
||||
private abstract class BaseClientExecutable<T extends IClientExecutable<?, ?>, Y> implements IClientExecutable<T, Y> {
|
||||
private EncodingEnum myParamEncoding;
|
||||
private Boolean myPrettyPrint;
|
||||
private boolean myQueryLogRequestAndResponse;
|
||||
|
||||
protected void addParam(Map<String, List<String>> params, String parameterName, String parameterValue) {
|
||||
if (!params.containsKey(parameterName)) {
|
||||
params.put(parameterName, new ArrayList<String>());
|
||||
}
|
||||
params.get(parameterName).add(parameterValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T andLogRequestAndResponse(boolean theLogRequestAndResponse) {
|
||||
|
@ -575,11 +581,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
}
|
||||
|
||||
private class CreateInternal extends BaseClientExecutable<ICreateTyped, MethodOutcome> implements ICreate, ICreateTyped {
|
||||
private class CreateInternal extends BaseClientExecutable<ICreateTyped, MethodOutcome> implements ICreate, ICreateTyped, ICreateWithQuery, ICreateWithQueryTyped {
|
||||
|
||||
private String myId;
|
||||
private IResource myResource;
|
||||
private String myResourceBody;
|
||||
private String mySearchUrl;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
|
@ -593,7 +601,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myResourceBody = null;
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext, mySearchUrl);
|
||||
} else if (myCriterionList != null) {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext, myCriterionList.toParamList());
|
||||
} else {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
@ -631,15 +646,50 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQuery conditional() {
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> implements IDelete, IDeleteTyped {
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> implements IDelete, IDeleteTyped, IDeleteWithQuery, IDeleteWithQueryTyped {
|
||||
|
||||
private IdDt myId;
|
||||
private String mySearchUrl;
|
||||
private String myResourceType;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public BaseOperationOutcome execute() {
|
||||
HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(myId);
|
||||
HttpDeleteClientInvocation invocation;
|
||||
if (myId != null) {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myId);
|
||||
} else if (myCriterionList != null) {
|
||||
Map<String, List<String>> params = myCriterionList.toParamList();
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myResourceType, params);
|
||||
} else {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(mySearchUrl);
|
||||
}
|
||||
OperationOutcomeResponseHandler binding = new OperationOutcomeResponseHandler();
|
||||
Map<String, List<String>> params = new HashMap<String, List<String>>();
|
||||
return invoke(params, binding, invocation);
|
||||
|
@ -680,6 +730,56 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myId = new IdDt(theResourceType, theLogicalId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteTyped resourceConditionalByUrl(String theSearchUrl) {
|
||||
Validate.notBlank(theSearchUrl, "theSearchUrl can not be blank/null");
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQuery resourceConditionalByType(String theResourceType) {
|
||||
Validate.notBlank(theResourceType, "theResourceType can not be blank/null");
|
||||
if (myContext.getResourceDefinition(theResourceType) == null) {
|
||||
throw new IllegalArgumentException("Unknown resource type: " + theResourceType);
|
||||
}
|
||||
myResourceType = theResourceType;
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CriterionList extends ArrayList<ICriterionInternal> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public void populateParamList(Map<String, List<String>> theParams) {
|
||||
for (ICriterionInternal next : this) {
|
||||
String parameterName = next.getParameterName();
|
||||
String parameterValue = next.getParameterValue();
|
||||
addParam(theParams, parameterName, parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, List<String>> toParamList() {
|
||||
LinkedHashMap<String, List<String>> retVal = new LinkedHashMap<String, List<String>>();
|
||||
populateParamList(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class GetPageInternal extends BaseClientExecutable<IGetPageTyped, Bundle> implements IGetPageTyped {
|
||||
|
@ -996,7 +1096,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private class SearchInternal extends BaseClientExecutable<IQuery, Bundle> implements IQuery, IUntypedQuery {
|
||||
|
||||
private String myCompartmentName;
|
||||
private List<ICriterionInternal> myCriterion = new ArrayList<ICriterionInternal>();
|
||||
private CriterionList myCriterion = new CriterionList();
|
||||
private List<Include> myInclude = new ArrayList<Include>();
|
||||
private Integer myParamLimit;
|
||||
private String myResourceId;
|
||||
|
@ -1025,11 +1125,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
// params.putAll(initial);
|
||||
// }
|
||||
|
||||
for (ICriterionInternal next : myCriterion) {
|
||||
String parameterName = next.getParameterName();
|
||||
String parameterValue = next.getParameterValue();
|
||||
addParam(params, parameterName, parameterValue);
|
||||
}
|
||||
myCriterion.populateParamList(params);
|
||||
|
||||
for (Include next : myInclude) {
|
||||
addParam(params, Constants.PARAM_INCLUDE, next.getValue());
|
||||
|
@ -1224,30 +1320,39 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable {
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
|
||||
|
||||
private IdDt myId;
|
||||
private IResource myResource;
|
||||
private String myResourceBody;
|
||||
private String mySearchUrl;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
if (myResource == null) {
|
||||
myResource = parseResourceBody(myResourceBody);
|
||||
}
|
||||
if (myId == null) {
|
||||
myId = myResource.getId();
|
||||
}
|
||||
if (myId == null || myId.hasIdPart() == false) {
|
||||
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
|
||||
}
|
||||
|
||||
// If an explicit encoding is chosen, we will re-serialize to ensure the right encoding
|
||||
if (getParamEncoding() != null) {
|
||||
myResourceBody = null;
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = MethodUtil.createUpdateInvocation(myContext, myResource, myResourceBody, mySearchUrl);
|
||||
} else if (myCriterionList != null) {
|
||||
invocation = MethodUtil.createUpdateInvocation(myContext, myResource, myResourceBody, myCriterionList.toParamList());
|
||||
} else {
|
||||
if (myId == null) {
|
||||
myId = myResource.getId();
|
||||
}
|
||||
if (myId == null || myId.hasIdPart() == false) {
|
||||
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
|
||||
}
|
||||
invocation = MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
@ -1297,6 +1402,30 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQuery conditional() {
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IBaseQuery<T> {
|
||||
|
||||
T where(ICriterion<?> theCriterion);
|
||||
|
||||
T and(ICriterion<?> theCriterion);
|
||||
|
||||
}
|
|
@ -37,4 +37,19 @@ public interface ICreateTyped extends IClientExecutable<ICreateTyped, MethodOutc
|
|||
*/
|
||||
ICreateTyped withId(IdDt theId);
|
||||
|
||||
/**
|
||||
* Specifies that the create should be performed as a conditional create
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
ICreateTyped conditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
ICreateWithQuery conditional();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
|
||||
public interface ICreateWithQuery extends IBaseQuery<ICreateWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface ICreateWithQueryTyped extends ICreateTyped, ICreateWithQuery {
|
||||
|
||||
}
|
|
@ -30,5 +30,20 @@ public interface IDelete {
|
|||
IDeleteTyped resourceById(IdDt theId);
|
||||
|
||||
IDeleteTyped resourceById(String theResourceType, String theLogicalId);
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that the delete should be performed as a conditional delete
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IDeleteTyped resourceConditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IDeleteWithQuery resourceConditionalByType(String theResourceType);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IDeleteWithQuery extends IBaseQuery<IDeleteWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IDeleteWithQueryTyped extends IDeleteTyped, IDeleteWithQuery {
|
||||
|
||||
}
|
|
@ -24,11 +24,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
|
||||
public interface IQuery extends IClientExecutable<IQuery,Bundle> {
|
||||
|
||||
IQuery where(ICriterion<?> theCriterion);
|
||||
|
||||
IQuery and(ICriterion<?> theCriterion);
|
||||
public interface IQuery extends IClientExecutable<IQuery, Bundle>, IBaseQuery<IQuery> {
|
||||
|
||||
IQuery include(Include theIncludeManagingorganization);
|
||||
|
||||
|
|
|
@ -28,4 +28,19 @@ public interface IUpdateTyped extends IUpdateExecutable {
|
|||
|
||||
IUpdateExecutable withId(String theId);
|
||||
|
||||
/**
|
||||
* Specifies that the update should be performed as a conditional create
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IUpdateTyped conditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IUpdateWithQuery conditional();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
|
||||
public interface IUpdateWithQuery extends IBaseQuery<IUpdateWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IUpdateWithQueryTyped extends IUpdateTyped, IUpdateWithQuery {
|
||||
|
||||
}
|
|
@ -143,29 +143,55 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
myResources = null;
|
||||
myBundle = null;
|
||||
myContents = theContents;
|
||||
myContentsIsBundle = false;
|
||||
myParams = theParams;
|
||||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
myResource = theResource;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
myResources = null;
|
||||
myBundle = null;
|
||||
myContents = null;
|
||||
myContentsIsBundle = false;
|
||||
myParams = theParams;
|
||||
myBundleType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding) throws DataFormatException {
|
||||
StringBuilder b = new StringBuilder();
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
if (myUrlPath == null) {
|
||||
b.append(theUrlBase);
|
||||
url.append(theUrlBase);
|
||||
} else {
|
||||
if (!myUrlPath.contains("://")) {
|
||||
b.append(theUrlBase);
|
||||
url.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/")) {
|
||||
b.append('/');
|
||||
url.append('/');
|
||||
}
|
||||
}
|
||||
b.append(myUrlPath);
|
||||
url.append(myUrlPath);
|
||||
}
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
|
||||
String url = b.toString();
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, url, url.indexOf("?") == -1);
|
||||
|
||||
if (myResource != null && BaseBinary.class.isAssignableFrom(myResource.getClass())) {
|
||||
BaseBinary binary = (BaseBinary) myResource;
|
||||
ByteArrayEntity entity = new ByteArrayEntity(binary.getContent(), ContentType.parse(binary.getContentType()));
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
addMatchHeaders(retVal, url);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -177,7 +203,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
if (myContents != null) {
|
||||
encoding = MethodUtil.detectEncoding(myContents);
|
||||
}
|
||||
|
||||
|
||||
if (encoding == EncodingEnum.JSON) {
|
||||
parser = myContext.newJsonParser();
|
||||
} else {
|
||||
|
@ -187,12 +213,12 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
|
||||
AbstractHttpEntity entity;
|
||||
if (myParams != null) {
|
||||
contentType= null;
|
||||
contentType = null;
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
for (Entry<String, List<String>> nextParam : myParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for(String s: value){
|
||||
parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
|
||||
for (String s : value) {
|
||||
parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -228,6 +254,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
super.addHeadersToRequest(retVal);
|
||||
addMatchHeaders(retVal, url);
|
||||
|
||||
if (contentType != null) {
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
|
@ -236,6 +263,41 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(String url, AbstractHttpEntity theEntity);
|
||||
private void addMatchHeaders(HttpRequestBase theHttpRequest, StringBuilder theUrlBase) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
|
||||
if (myIfNoneExistString != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
b.append(b.indexOf("?") == -1 ? '?' : '&');
|
||||
b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
|
||||
b.deleteCharAt(b.length() - 1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity);
|
||||
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
|
||||
public void setIfNoneExistParams(Map<String, List<String>> theIfNoneExist) {
|
||||
myIfNoneExistParams = theIfNoneExist;
|
||||
}
|
||||
|
||||
public void setIfNoneExistString(String theIfNoneExistString) {
|
||||
myIfNoneExistString = theIfNoneExistString;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,15 +26,12 @@ import java.io.IOException;
|
|||
import java.io.Reader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
|
@ -47,6 +44,18 @@ import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.AddTags;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.DeleteTags;
|
||||
import ca.uhn.fhir.rest.annotation.GetTags;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
|
@ -61,9 +70,9 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionNotSpecifiedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
@ -217,7 +226,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
ex = new ResourceVersionConflictException("Server responded with HTTP 409");
|
||||
break;
|
||||
case Constants.STATUS_HTTP_412_PRECONDITION_FAILED:
|
||||
ex = new ResourceVersionNotSpecifiedException("Server responded with HTTP 412");
|
||||
ex = new PreconditionFailedException("Server responded with HTTP 412");
|
||||
break;
|
||||
case Constants.STATUS_HTTP_422_UNPROCESSABLE_ENTITY:
|
||||
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theStatusCode);
|
||||
|
|
|
@ -273,11 +273,16 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
BufferedReader requestReader = theRequest.getServletRequest().getReader();
|
||||
|
||||
Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType();
|
||||
IResource retVal;
|
||||
if (wantedResourceType != null) {
|
||||
return (IResource) parser.parseResource(wantedResourceType, requestReader);
|
||||
retVal = (IResource) parser.parseResource(wantedResourceType, requestReader);
|
||||
} else {
|
||||
return parser.parseResource(requestReader);
|
||||
retVal = parser.parseResource(requestReader);
|
||||
}
|
||||
|
||||
retVal.setId(theRequest.getId());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract Set<RequestType> provideAllowableRequestTypes();
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
class ConditionalParamBinder implements IParameter {
|
||||
|
||||
ConditionalParamBinder() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments) throws InternalErrorException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
if (theRequest.getId() != null && theRequest.getId().hasIdPart()) {
|
||||
return null;
|
||||
}
|
||||
int questionMarkIndex = theRequest.getCompleteUrl().indexOf('?');
|
||||
return theRequest.getResourceName() + theRequest.getCompleteUrl().substring(questionMarkIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,8 @@ package ca.uhn.fhir.rest.method;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
|
@ -154,5 +156,14 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theSearchUrl) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theSearchUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
return new HttpDeleteClientInvocation(theResourceType, theParams);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -33,12 +33,22 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
|||
public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
||||
|
||||
private String myUrlPath;
|
||||
private Map<String, List<String>> myParams;
|
||||
|
||||
public HttpDeleteClientInvocation(IdDt theId) {
|
||||
super();
|
||||
myUrlPath = theId.toUnqualifiedVersionless().getValue();
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theSearchUrl) {
|
||||
myUrlPath = theSearchUrl;
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
myUrlPath = theResourceType;
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
@ -48,12 +58,12 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
|||
}
|
||||
b.append(myUrlPath);
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b,b.indexOf("?") == -1);
|
||||
appendExtraParamsWithQuestionMark(myParams, b, b.indexOf("?") == -1);
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
|
||||
|
||||
HttpDelete retVal = new HttpDelete(b.toString());
|
||||
super.addHeadersToRequest(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -34,38 +34,34 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
|||
|
||||
public class HttpPostClientInvocation extends BaseHttpClientInvocationWithContents {
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, IResource theResource, String theUrlExtension) {
|
||||
super(theContext, theResource, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, TagList theTagList, String... theUrlExtension) {
|
||||
super(theContext, theTagList, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, List<IResource> theResources, BundleTypeEnum theBundleType) {
|
||||
super(theContext, theResources, theBundleType);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, Bundle theBundle) {
|
||||
super(theContext,theBundle);
|
||||
super(theContext, theBundle);
|
||||
}
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlExtension) {
|
||||
super(theContext,theContents, theIsBundle, theUrlExtension);
|
||||
super(theContext, theContents, theIsBundle, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, Map<String, List<String>> theParams, String... theUrlExtension) {
|
||||
super(theContext, theParams, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpPost createRequest(String url, AbstractHttpEntity theEntity) {
|
||||
HttpPost retVal = new HttpPost(url);
|
||||
protected HttpPost createRequest(StringBuilder theUrlBase, AbstractHttpEntity theEntity) {
|
||||
HttpPost retVal = new HttpPost(theUrlBase.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -34,15 +34,14 @@ public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContent
|
|||
}
|
||||
|
||||
public HttpPutClientInvocation(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlExtension) {
|
||||
super(theContext,theContents, theIsBundle, theUrlExtension);
|
||||
super(theContext, theContents, theIsBundle, theUrlExtension);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestBase createRequest(String url, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(url);
|
||||
protected HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(theUrl.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,14 +5,17 @@ import static org.apache.commons.lang3.StringUtils.*;
|
|||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
@ -44,6 +47,7 @@ import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalOperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
|
@ -95,9 +99,65 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
|||
|
||||
public class MethodUtil {
|
||||
private static final String LABEL = "label=\"";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
|
||||
private static final String SCHEME = "scheme=\"";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
|
||||
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (list != null) {
|
||||
for (Tag tag : list) {
|
||||
if (StringUtils.isNotBlank(tag.getTerm())) {
|
||||
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, FhirContext theContext) {
|
||||
return createCreateInvocation(theResource, null, null, theContext);
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
|
||||
if (StringUtils.isNotBlank(theId)) {
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(theId);
|
||||
}
|
||||
|
||||
HttpPostClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResource, urlExtension.toString());
|
||||
} else {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResourceBody, false, urlExtension.toString());
|
||||
}
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, Map<String, List<String>> theIfNoneExistParams) {
|
||||
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
|
||||
retVal.setIfNoneExistParams(theIfNoneExistParams);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, String theIfNoneExistUrl) {
|
||||
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
|
||||
retVal.setIfNoneExistString(theIfNoneExistUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, String theResourceBody, IdDt theId, FhirContext theContext) {
|
||||
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||
|
@ -105,9 +165,9 @@ public class MethodUtil {
|
|||
urlBuilder.append(resourceName);
|
||||
urlBuilder.append('/');
|
||||
urlBuilder.append(theId.getIdPart());
|
||||
String urlExtension = urlBuilder.toString();
|
||||
|
||||
HttpPutClientInvocation retVal;
|
||||
String urlExtension = urlBuilder.toString();
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, urlExtension);
|
||||
} else {
|
||||
|
@ -135,203 +195,49 @@ public class MethodUtil {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static void parseClientRequestResourceHeaders(IdDt theRequestedId, Map<String, List<String>> theHeaders, IBaseResource resource) {
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
String headerValue = lmHeaders.get(0);
|
||||
Date headerDateValue;
|
||||
try {
|
||||
headerDateValue = DateUtils.parseDate(headerValue);
|
||||
if (resource instanceof IResource) {
|
||||
InstantDt lmValue = new InstantDt(headerDateValue);
|
||||
((IResource) resource).getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, lmValue);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
((IAnyResource) resource).getMeta().setLastUpdated(headerDateValue);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.warn("Unable to parse date string '{}'. Error is: {}", headerValue, e.toString());
|
||||
}
|
||||
}
|
||||
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, Map<String, List<String>> theMatchParams) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
List<String> clHeaders = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clHeaders != null && clHeaders.size() > 0 && StringUtils.isNotBlank(clHeaders.get(0))) {
|
||||
String headerValue = clHeaders.get(0);
|
||||
if (isNotBlank(headerValue)) {
|
||||
new IdDt(headerValue).applyTo(resource);
|
||||
}
|
||||
}
|
||||
String resourceType = theContext.getResourceDefinition(theResource).getName();
|
||||
b.append(resourceType);
|
||||
|
||||
IdDt existing = IdDt.of(resource);
|
||||
|
||||
List<String> eTagHeaders = theHeaders.get(Constants.HEADER_ETAG_LC);
|
||||
String eTagVersion = null;
|
||||
if (eTagHeaders != null && eTagHeaders.size() > 0) {
|
||||
eTagVersion = parseETagValue(eTagHeaders.get(0));
|
||||
}
|
||||
if (isNotBlank(eTagVersion)) {
|
||||
if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing.hasVersionIdPart() == false) {
|
||||
existing.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> categoryHeaders = theHeaders.get(Constants.HEADER_CATEGORY_LC);
|
||||
if (categoryHeaders != null && categoryHeaders.size() > 0 && StringUtils.isNotBlank(categoryHeaders.get(0))) {
|
||||
TagList tagList = new TagList();
|
||||
for (String header : categoryHeaders) {
|
||||
parseTagValue(tagList, header);
|
||||
}
|
||||
if (resource instanceof IResource) {
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) resource, tagList);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
IMetaType meta = ((IAnyResource) resource).getMeta();
|
||||
for (Tag next : tagList) {
|
||||
meta.addTag().setSystem(next.getScheme()).setCode(next.getTerm()).setDisplay(next.getLabel());
|
||||
boolean haveQuestionMark = false;
|
||||
for (Entry<String, List<String>> nextEntry : theMatchParams.entrySet()) {
|
||||
for (String nextValue : nextEntry.getValue()) {
|
||||
b.append(haveQuestionMark ? '&' : '?');
|
||||
haveQuestionMark = true;
|
||||
try {
|
||||
b.append(URLEncoder.encode(nextEntry.getKey(), "UTF-8"));
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ConfigurationException("UTF-8 not supported on this platform");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String parseETagValue(String value) {
|
||||
String eTagVersion;
|
||||
value = value.trim();
|
||||
if (value.length() > 1) {
|
||||
if (value.charAt(value.length() - 1) == '"') {
|
||||
if (value.charAt(0) == '"') {
|
||||
eTagVersion = value.substring(1, value.length() - 1);
|
||||
} else if (value.length() > 3 && value.charAt(0) == 'W' && value.charAt(1) == '/' && value.charAt(2) == '"') {
|
||||
eTagVersion = value.substring(3, value.length() - 1);
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
return eTagVersion;
|
||||
}
|
||||
|
||||
public static void parseTagValue(TagList tagList, String nextTagComplete) {
|
||||
StringBuilder next = new StringBuilder(nextTagComplete);
|
||||
parseTagValue(tagList, nextTagComplete, next);
|
||||
}
|
||||
|
||||
private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
|
||||
int firstSemicolon = theBuffer.indexOf(";");
|
||||
int deleteTo;
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.indexOf(",");
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.length();
|
||||
deleteTo = theBuffer.length();
|
||||
} else {
|
||||
deleteTo = firstSemicolon;
|
||||
}
|
||||
} else {
|
||||
deleteTo = firstSemicolon + 1;
|
||||
}
|
||||
|
||||
String term = theBuffer.substring(0, firstSemicolon);
|
||||
String scheme = null;
|
||||
String label = null;
|
||||
if (isBlank(term)) {
|
||||
return;
|
||||
}
|
||||
|
||||
theBuffer.delete(0, deleteTo);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
while (theBuffer.length() > 0) {
|
||||
boolean foundSomething = false;
|
||||
if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
|
||||
scheme = theBuffer.substring(SCHEME.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", LABEL.length());
|
||||
label = theBuffer.substring(LABEL.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
// TODO: support enc2231-string as described in
|
||||
// http://tools.ietf.org/html/draft-johnston-http-category-header-02
|
||||
// TODO: support multiple tags in one header as described in
|
||||
// http://hl7.org/implement/standards/fhir/http.html#tags
|
||||
|
||||
while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
if (!foundSomething) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
|
||||
} else {
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0) {
|
||||
ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
|
||||
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (list != null) {
|
||||
for (Tag tag : list) {
|
||||
if (StringUtils.isNotBlank(tag.getTerm())) {
|
||||
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, FhirContext theContext) {
|
||||
return createCreateInvocation(theResource, null, null, theContext);
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
if (StringUtils.isNotBlank(theId)) {
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(theId);
|
||||
}
|
||||
|
||||
HttpPostClientInvocation retVal;
|
||||
HttpPutClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResource, urlExtension.toString());
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, b.toString());
|
||||
} else {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResourceBody, false, urlExtension.toString());
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, b.toString());
|
||||
}
|
||||
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, String theMatchUrl) {
|
||||
HttpPutClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, theMatchUrl);
|
||||
} else {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, theMatchUrl);
|
||||
}
|
||||
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -339,66 +245,30 @@ public class MethodUtil {
|
|||
public static EncodingEnum detectEncoding(String theBody) {
|
||||
for (int i = 0; i < theBody.length(); i++) {
|
||||
switch (theBody.charAt(i)) {
|
||||
case '<':
|
||||
return EncodingEnum.XML;
|
||||
case '{':
|
||||
return EncodingEnum.JSON;
|
||||
case '<':
|
||||
return EncodingEnum.XML;
|
||||
case '{':
|
||||
return EncodingEnum.JSON;
|
||||
}
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
}
|
||||
|
||||
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
|
||||
List<String> locationHeaders = new ArrayList<String>();
|
||||
List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC);
|
||||
if (lh != null) {
|
||||
locationHeaders.addAll(lh);
|
||||
}
|
||||
List<String> clh = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clh != null) {
|
||||
locationHeaders.addAll(clh);
|
||||
}
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
if (locationHeaders != null && locationHeaders.size() > 0) {
|
||||
String locationHeader = locationHeaders.get(0);
|
||||
BaseOutcomeReturningMethodBinding.parseContentLocation(retVal, theResourceName, locationHeader);
|
||||
}
|
||||
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
||||
EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (ct != null) {
|
||||
PushbackReader reader = new PushbackReader(theResponseReader);
|
||||
|
||||
try {
|
||||
int firstByte = reader.read();
|
||||
if (firstByte == -1) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read");
|
||||
reader = null;
|
||||
} else {
|
||||
reader.unread(firstByte);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read", e);
|
||||
reader = null;
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
for (Annotation annotation : theAnnotations) {
|
||||
if (annotation instanceof Description) {
|
||||
Description desc = (Description) annotation;
|
||||
if (isNotBlank(desc.formalDefinition())) {
|
||||
theParameter.setDescription(desc.formalDefinition());
|
||||
} else {
|
||||
theParameter.setDescription(desc.shortDefinition());
|
||||
}
|
||||
|
||||
if (reader != null) {
|
||||
IParser parser = ct.newParser(theContext);
|
||||
IResource outcome = parser.parseResource(reader);
|
||||
if (outcome instanceof BaseOperationOutcome) {
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) outcome);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static Integer findIdParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
|
||||
|
@ -416,38 +286,12 @@ public class MethodUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
for (Annotation annotation : theAnnotations) {
|
||||
if (annotation instanceof Description) {
|
||||
Description desc = (Description) annotation;
|
||||
if (isNotBlank(desc.formalDefinition())) {
|
||||
theParameter.setDescription(desc.formalDefinition());
|
||||
} else {
|
||||
theParameter.setDescription(desc.shortDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
public static Integer findTagListParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
|
||||
}
|
||||
|
||||
public static IQueryParameterOr<?> singleton(final IQueryParameterType theParam) {
|
||||
return new IQueryParameterOr<IQueryParameterType>() {
|
||||
|
||||
@Override
|
||||
public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
|
||||
if (theParameters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (theParameters.size() > 1) {
|
||||
throw new IllegalArgumentException("Type " + theParam.getClass().getCanonicalName() + " does not support multiple values");
|
||||
}
|
||||
theParam.setValueAsQueryToken(theParameters.getQualifier(), theParameters.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IQueryParameterType> getValuesAsQueryTokens() {
|
||||
return Collections.singletonList(theParam);
|
||||
}
|
||||
};
|
||||
public static Integer findConditionalOperationParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, ConditionalOperationParam.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -455,46 +299,6 @@ public class MethodUtil {
|
|||
return MethodUtil.findParamAnnotationIndex(theMethod, VersionIdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findIdParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findTagListParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (theParamDef.getParamType()) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
return binder.parse(theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(FhirContext theContext, Method theMethod, Object theProvider) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
|
@ -591,6 +395,8 @@ public class MethodUtil {
|
|||
param = new SortParameter();
|
||||
} else if (nextAnnotation instanceof TransactionParam) {
|
||||
param = new TransactionParamBinder(theContext);
|
||||
} else if (nextAnnotation instanceof ConditionalOperationParam) {
|
||||
param = new ConditionalParamBinder();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
@ -612,4 +418,267 @@ public class MethodUtil {
|
|||
return parameters;
|
||||
}
|
||||
|
||||
public static void parseClientRequestResourceHeaders(IdDt theRequestedId, Map<String, List<String>> theHeaders, IBaseResource resource) {
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
String headerValue = lmHeaders.get(0);
|
||||
Date headerDateValue;
|
||||
try {
|
||||
headerDateValue = DateUtils.parseDate(headerValue);
|
||||
if (resource instanceof IResource) {
|
||||
InstantDt lmValue = new InstantDt(headerDateValue);
|
||||
((IResource) resource).getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, lmValue);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
((IAnyResource) resource).getMeta().setLastUpdated(headerDateValue);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.warn("Unable to parse date string '{}'. Error is: {}", headerValue, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> clHeaders = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clHeaders != null && clHeaders.size() > 0 && StringUtils.isNotBlank(clHeaders.get(0))) {
|
||||
String headerValue = clHeaders.get(0);
|
||||
if (isNotBlank(headerValue)) {
|
||||
new IdDt(headerValue).applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
IdDt existing = IdDt.of(resource);
|
||||
|
||||
List<String> eTagHeaders = theHeaders.get(Constants.HEADER_ETAG_LC);
|
||||
String eTagVersion = null;
|
||||
if (eTagHeaders != null && eTagHeaders.size() > 0) {
|
||||
eTagVersion = parseETagValue(eTagHeaders.get(0));
|
||||
}
|
||||
if (isNotBlank(eTagVersion)) {
|
||||
if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing.hasVersionIdPart() == false) {
|
||||
existing.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> categoryHeaders = theHeaders.get(Constants.HEADER_CATEGORY_LC);
|
||||
if (categoryHeaders != null && categoryHeaders.size() > 0 && StringUtils.isNotBlank(categoryHeaders.get(0))) {
|
||||
TagList tagList = new TagList();
|
||||
for (String header : categoryHeaders) {
|
||||
parseTagValue(tagList, header);
|
||||
}
|
||||
if (resource instanceof IResource) {
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) resource, tagList);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
IMetaType meta = ((IAnyResource) resource).getMeta();
|
||||
for (Tag next : tagList) {
|
||||
meta.addTag().setSystem(next.getScheme()).setCode(next.getTerm()).setDisplay(next.getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String parseETagValue(String value) {
|
||||
String eTagVersion;
|
||||
value = value.trim();
|
||||
if (value.length() > 1) {
|
||||
if (value.charAt(value.length() - 1) == '"') {
|
||||
if (value.charAt(0) == '"') {
|
||||
eTagVersion = value.substring(1, value.length() - 1);
|
||||
} else if (value.length() > 3 && value.charAt(0) == 'W' && value.charAt(1) == '/' && value.charAt(2) == '"') {
|
||||
eTagVersion = value.substring(3, value.length() - 1);
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
return eTagVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (theParamDef.getParamType()) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
return binder.parse(theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
public static void parseTagValue(TagList tagList, String nextTagComplete) {
|
||||
StringBuilder next = new StringBuilder(nextTagComplete);
|
||||
parseTagValue(tagList, nextTagComplete, next);
|
||||
}
|
||||
|
||||
private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
|
||||
int firstSemicolon = theBuffer.indexOf(";");
|
||||
int deleteTo;
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.indexOf(",");
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.length();
|
||||
deleteTo = theBuffer.length();
|
||||
} else {
|
||||
deleteTo = firstSemicolon;
|
||||
}
|
||||
} else {
|
||||
deleteTo = firstSemicolon + 1;
|
||||
}
|
||||
|
||||
String term = theBuffer.substring(0, firstSemicolon);
|
||||
String scheme = null;
|
||||
String label = null;
|
||||
if (isBlank(term)) {
|
||||
return;
|
||||
}
|
||||
|
||||
theBuffer.delete(0, deleteTo);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
while (theBuffer.length() > 0) {
|
||||
boolean foundSomething = false;
|
||||
if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
|
||||
scheme = theBuffer.substring(SCHEME.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", LABEL.length());
|
||||
label = theBuffer.substring(LABEL.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
// TODO: support enc2231-string as described in
|
||||
// http://tools.ietf.org/html/draft-johnston-http-category-header-02
|
||||
// TODO: support multiple tags in one header as described in
|
||||
// http://hl7.org/implement/standards/fhir/http.html#tags
|
||||
|
||||
while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
if (!foundSomething) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
|
||||
} else {
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0) {
|
||||
ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
|
||||
List<String> locationHeaders = new ArrayList<String>();
|
||||
List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC);
|
||||
if (lh != null) {
|
||||
locationHeaders.addAll(lh);
|
||||
}
|
||||
List<String> clh = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clh != null) {
|
||||
locationHeaders.addAll(clh);
|
||||
}
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
if (locationHeaders != null && locationHeaders.size() > 0) {
|
||||
String locationHeader = locationHeaders.get(0);
|
||||
BaseOutcomeReturningMethodBinding.parseContentLocation(retVal, theResourceName, locationHeader);
|
||||
}
|
||||
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
||||
EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (ct != null) {
|
||||
PushbackReader reader = new PushbackReader(theResponseReader);
|
||||
|
||||
try {
|
||||
int firstByte = reader.read();
|
||||
if (firstByte == -1) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read");
|
||||
reader = null;
|
||||
} else {
|
||||
reader.unread(firstByte);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read", e);
|
||||
reader = null;
|
||||
}
|
||||
|
||||
if (reader != null) {
|
||||
IParser parser = ct.newParser(theContext);
|
||||
IResource outcome = parser.parseResource(reader);
|
||||
if (outcome instanceof BaseOperationOutcome) {
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) outcome);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static IQueryParameterOr<?> singleton(final IQueryParameterType theParam) {
|
||||
return new IQueryParameterOr<IQueryParameterType>() {
|
||||
|
||||
@Override
|
||||
public List<IQueryParameterType> getValuesAsQueryTokens() {
|
||||
return Collections.singletonList(theParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
|
||||
if (theParameters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (theParameters.size() > 1) {
|
||||
throw new IllegalArgumentException("Type " + theParam.getClass().getCanonicalName() + " does not support multiple values");
|
||||
}
|
||||
theParam.setValueAsQueryToken(theParameters.getQualifier(), theParameters.get(0));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,19 +20,17 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
|
@ -43,16 +41,11 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
private Integer myVersionIdParameterIndex;
|
||||
|
||||
public UpdateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(theMethod, theContext, Update.class, theProvider);
|
||||
|
||||
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod);
|
||||
if (myIdParameterIndex == null) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has no parameter annotated with the @" + IdParam.class.getSimpleName() + " annotation");
|
||||
}
|
||||
myVersionIdParameterIndex = MethodUtil.findVersionIdParameterIndex(theMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,7 +85,7 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
|
||||
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
|
||||
if (id != null && id.hasVersionIdPart()) {
|
||||
theRequest.setId(id);
|
||||
theRequest.getId().setValue(id.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,9 +97,8 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
}
|
||||
}
|
||||
|
||||
theParams[myIdParameterIndex] = theRequest.getId();
|
||||
if (myVersionIdParameterIndex != null) {
|
||||
theParams[myVersionIdParameterIndex] = theRequest.getId();
|
||||
if (myIdParameterIndex != null) {
|
||||
theParams[myIdParameterIndex] = theRequest.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,12 +109,6 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
throw new NullPointerException("ID can not be null");
|
||||
}
|
||||
|
||||
if (myVersionIdParameterIndex != null) {
|
||||
IdDt versionIdDt = (IdDt) theArgs[myVersionIdParameterIndex];
|
||||
if (idDt.hasVersionIdPart() == false) {
|
||||
idDt = idDt.withVersion(versionIdDt.getIdPart());
|
||||
}
|
||||
}
|
||||
FhirContext context = getContext();
|
||||
|
||||
HttpPutClientInvocation retVal = MethodUtil.createUpdateInvocation(theResource, null, idDt, context);
|
||||
|
|
|
@ -49,8 +49,7 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
||||
public class InternalCodingDt
|
||||
extends BaseCodingDt implements ICompositeDatatype
|
||||
public class InternalCodingDt extends BaseCodingDt implements ICompositeDatatype
|
||||
{
|
||||
|
||||
/**
|
||||
|
|
|
@ -111,6 +111,8 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String HEADER_IF_NONE_EXIST = "If-None-Exist";
|
||||
public static final String HEADER_IF_NONE_EXIST_LC = HEADER_IF_NONE_EXIST.toLowerCase();
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
public interface IAnyResource extends IBaseResource {
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
public interface IBackboneElement {
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBase;
|
||||
|
||||
public interface IBackboneElement extends IBase {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IPrimitiveType;
|
||||
|
||||
public interface IBaseBooleanDatatype extends IPrimitiveType<Boolean> {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
public interface IBaseBundle extends IBaseResource {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBase;
|
||||
|
||||
public interface IBaseDatatype extends IBase {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.math.BigDecimal;
|
||||
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IBaseElement {
|
||||
|
||||
IBaseElement setId(String theValue);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface IBaseEnumFactory<T extends Enum<?>> {
|
||||
|
||||
/**
|
||||
* Read an enumeration value from the string that represents it on the XML or JSON
|
||||
*
|
||||
* @param codeString the value found in the XML or JSON
|
||||
* @return the enumeration value
|
||||
* @throws IllegalArgumentException is the value is not known
|
||||
*/
|
||||
public T fromCode(String codeString) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get the XML/JSON representation for an enumerated value
|
||||
*
|
||||
* @param code - the enumeration value
|
||||
* @return the XML/JSON representation
|
||||
*/
|
||||
public String toCode(T code);
|
||||
|
||||
}
|
|
@ -1,7 +1,39 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.ICompositeType;
|
||||
|
||||
public interface IBaseExtension extends ICompositeType {
|
||||
public interface IBaseExtension<T> extends ICompositeType {
|
||||
|
||||
List<T> getExtension();
|
||||
|
||||
String getUrl();
|
||||
|
||||
IBaseDatatype getValue();
|
||||
|
||||
T setUrl(String theUrl);
|
||||
|
||||
T setValue(IBaseDatatype theValue);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.util.List;
|
||||
|
||||
public interface IBaseHasExtensions {
|
||||
|
||||
public List<? extends IBaseExtension<?>> getExtension();
|
||||
|
||||
public IBaseExtension<?> addExtension();
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.util.List;
|
||||
|
||||
public interface IBaseHasModifierExtensions {
|
||||
|
||||
public List<? extends IBaseExtension<?>> getModifierExtension();
|
||||
|
||||
public IBaseExtension<?> addModifierExtension();
|
||||
|
||||
}
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IPrimitiveType;
|
||||
|
||||
public interface IBaseIntegerDatatype extends IPrimitiveType<Integer> {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
public interface ICoding {
|
||||
|
||||
ICoding setSystem(String theScheme);
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 ca.uhn.fhir.model.api.IElement;
|
||||
|
||||
public interface IDatatypeElement extends IElement {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.util.List;
|
||||
|
||||
public interface IDomainResource {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
|
||||
public interface IIdType {
|
||||
|
||||
|
|
|
@ -1,8 +1,30 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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 java.util.Date;
|
||||
|
||||
public interface IMetaType {
|
||||
import org.hl7.fhir.instance.model.ICompositeType;
|
||||
|
||||
public interface IMetaType extends ICompositeType {
|
||||
|
||||
ICoding addTag();
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.ICompositeType;
|
||||
|
||||
public interface INarrative extends ICompositeType {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* 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.hl7.fhir.instance.model.IBase;
|
||||
|
||||
public interface IReference extends IBase {
|
||||
|
|
|
@ -24,7 +24,16 @@ ca.uhn.fhir.validation.FhirValidator.noPhlocError=Phloc-schematron library not f
|
|||
|
||||
# JPA Messages
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionContainsMultipleWithDuplicateId=Transaction bundle contains multiple resources with ID: {0}
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionEntryHasInvalidVerb=Transaction bundle entry has missing or invalid HTTP Verb specified in Bundle.entry.transaction.method. Found value: "{0}"
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create entity with ID[{0}], this server does not allow clients to assign numeric IDs
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
|
|
|
@ -21,8 +21,8 @@ public class MultiVersionJsonParserTest {
|
|||
|
||||
String str = FhirContext.forDstu2().newJsonParser().encodeResourceToString(p);
|
||||
ourLog.info(str);
|
||||
|
||||
assertThat(str,StringContains.containsString("{\"resourceType\":\"Patient\",\"http://foo#ext\":[{\"valueQuantity\":{\"value\":2.2}}],\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]}"));
|
||||
|
||||
assertThat(str, StringContains.containsString("{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://foo#ext\",\"valueQuantity\":{\"value\":2.2}}],\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,22 +9,23 @@ import ca.uhn.fhir.validation.FhirValidator;
|
|||
|
||||
public class ValidatorTest {
|
||||
|
||||
@Test
|
||||
public void testValidator() {
|
||||
|
||||
FhirContext ctx = new FhirContext();
|
||||
FhirValidator val = ctx.newValidator();
|
||||
|
||||
// Phloc is not onthe classpath
|
||||
assertTrue(val.isValidateAgainstStandardSchema());
|
||||
assertFalse(val.isValidateAgainstStandardSchematron());
|
||||
@Test
|
||||
public void testValidator() {
|
||||
|
||||
FhirContext ctx = new FhirContext();
|
||||
FhirValidator val = ctx.newValidator();
|
||||
|
||||
// Phloc is not onthe classpath
|
||||
assertTrue(val.isValidateAgainstStandardSchema());
|
||||
assertFalse(val.isValidateAgainstStandardSchematron());
|
||||
|
||||
try {
|
||||
val.setValidateAgainstStandardSchematron(true);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Phloc-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try { val.setValidateAgainstStandardSchematron(true);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Phloc-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<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.7">
|
||||
<attributes>
|
||||
<attribute name="owner.project.facets" value="java"/>
|
||||
</attributes>
|
||||
|
|
|
@ -7,9 +7,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
|
|||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
|
@ -97,4 +97,4 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
|||
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<installed facet="jst.utility" version="1.0"/>
|
||||
<installed facet="java" version="1.6"/>
|
||||
<installed facet="java" version="1.7"/>
|
||||
</faceted-project>
|
||||
|
|
|
@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -48,6 +50,8 @@ import javax.persistence.criteria.Root;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -77,6 +81,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
|
@ -87,6 +92,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -95,15 +102,16 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
|||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public abstract class BaseFhirDao implements IDao {
|
||||
|
||||
public static final String UCUM_NS = "http://unitsofmeasure.org";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirDao.class);
|
||||
|
||||
private static final Map<FhirVersionEnum, FhirContext> ourRetrievalContexts = new HashMap<FhirVersionEnum, FhirContext>();
|
||||
public static final String UCUM_NS = "http://unitsofmeasure.org";
|
||||
|
||||
@Autowired(required = true)
|
||||
private DaoConfig myConfig;
|
||||
|
@ -114,8 +122,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
private EntityManager myEntityManager;
|
||||
|
||||
private List<IDaoListener> myListeners = new ArrayList<IDaoListener>();
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myPlatformTransactionManager;
|
||||
|
||||
|
@ -124,6 +130,8 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
private Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> myResourceTypeToDao;
|
||||
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
protected void createForcedIdIfNeeded(ResourceTable entity, IdDt id) {
|
||||
if (id.isEmpty() == false && id.hasIdPart()) {
|
||||
if (isValidPid(id)) {
|
||||
|
@ -196,7 +204,7 @@ public abstract class BaseFhirDao implements IDao {
|
|||
b.append(nextValue.getReference().getResourceType());
|
||||
b.append("] - Valid resource types for this server: ");
|
||||
b.append(myResourceTypeToDao.keySet().toString());
|
||||
|
||||
|
||||
throw new InvalidRequestException(b.toString());
|
||||
}
|
||||
Long valueOf;
|
||||
|
@ -508,19 +516,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
protected static String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
protected void notifyWriteCompleted() {
|
||||
for (IDaoListener next : myListeners) {
|
||||
next.writeCompleted();
|
||||
|
@ -579,6 +574,58 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
}
|
||||
|
||||
protected Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
protected SearchParameterMap translateMatchUrl(String theMatchUrl, RuntimeResourceDefinition resourceDef) {
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
String paramName = next.getName();
|
||||
String qualifier = null;
|
||||
for (int i = 0; i < paramMap.size(); i++) {
|
||||
switch (paramName.charAt(i)) {
|
||||
case '.':
|
||||
case ':':
|
||||
qualifier = paramName.substring(i);
|
||||
paramName = paramName.substring(0, i);
|
||||
i = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, next.getValue());
|
||||
nameToParamLists.put(paramName, paramList);
|
||||
}
|
||||
|
||||
for (String nextParamName : nameToParamLists.keySet()) {
|
||||
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
|
||||
if (paramDef == null) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
List<QualifiedParamList> paramList = nameToParamLists.get(nextParamName);
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(paramDef, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
}
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDaoListener(IDaoListener theListener) {
|
||||
Validate.notNull(theListener, "theListener");
|
||||
|
@ -832,7 +879,20 @@ public abstract class BaseFhirDao implements IDao {
|
|||
}
|
||||
}
|
||||
|
||||
protected String translatePidIdToForcedId(Long theId) {
|
||||
ForcedId forcedId = myEntityManager.find(ForcedId.class, theId);
|
||||
if (forcedId != null) {
|
||||
return forcedId.getForcedId();
|
||||
} else {
|
||||
return theId.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull) {
|
||||
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true);
|
||||
}
|
||||
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
|
||||
if (entity.getPublished() == null) {
|
||||
entity.setPublished(new Date());
|
||||
}
|
||||
|
@ -849,8 +909,10 @@ public abstract class BaseFhirDao implements IDao {
|
|||
myEntityManager.persist(historyEntry);
|
||||
}
|
||||
|
||||
entity.setVersion(entity.getVersion() + 1);
|
||||
|
||||
if (theUpdateVersion) {
|
||||
entity.setVersion(entity.getVersion() + 1);
|
||||
}
|
||||
|
||||
Collection<ResourceIndexedSearchParamString> paramsString = new ArrayList<ResourceIndexedSearchParamString>(entity.getParamsString());
|
||||
Collection<ResourceIndexedSearchParamToken> paramsToken = new ArrayList<ResourceIndexedSearchParamToken>(entity.getParamsToken());
|
||||
Collection<ResourceIndexedSearchParamNumber> paramsNumber = new ArrayList<ResourceIndexedSearchParamNumber>(entity.getParamsNumber());
|
||||
|
@ -858,12 +920,13 @@ public abstract class BaseFhirDao implements IDao {
|
|||
Collection<ResourceIndexedSearchParamDate> paramsDate = new ArrayList<ResourceIndexedSearchParamDate>(entity.getParamsDate());
|
||||
Collection<ResourceLink> resourceLinks = new ArrayList<ResourceLink>(entity.getResourceLinks());
|
||||
|
||||
final List<ResourceIndexedSearchParamString> stringParams;
|
||||
final List<ResourceIndexedSearchParamToken> tokenParams;
|
||||
final List<ResourceIndexedSearchParamNumber> numberParams;
|
||||
final List<ResourceIndexedSearchParamQuantity> quantityParams;
|
||||
final List<ResourceIndexedSearchParamDate> dateParams;
|
||||
final List<ResourceLink> links;
|
||||
List<ResourceIndexedSearchParamString> stringParams = null;
|
||||
List<ResourceIndexedSearchParamToken> tokenParams = null;
|
||||
List<ResourceIndexedSearchParamNumber> numberParams = null;
|
||||
List<ResourceIndexedSearchParamQuantity> quantityParams = null;
|
||||
List<ResourceIndexedSearchParamDate> dateParams = null;
|
||||
List<ResourceLink> links = null;
|
||||
|
||||
if (theDeletedTimestampOrNull != null) {
|
||||
|
||||
stringParams = Collections.emptyList();
|
||||
|
@ -875,7 +938,7 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity.setDeleted(theDeletedTimestampOrNull);
|
||||
entity.setUpdated(theDeletedTimestampOrNull);
|
||||
|
||||
} else {
|
||||
} else if (thePerformIndexing) {
|
||||
|
||||
stringParams = extractSearchParamStrings(entity, theResource);
|
||||
numberParams = extractSearchParamNumber(entity, theResource);
|
||||
|
@ -893,7 +956,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
links = extractResourceLinks(entity, theResource);
|
||||
populateResourceIntoEntity(theResource, entity);
|
||||
|
||||
entity.setUpdated(new Date());
|
||||
entity.setLanguage(theResource.getLanguage().getValue());
|
||||
entity.setParamsString(stringParams);
|
||||
|
@ -909,6 +971,12 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity.setResourceLinks(links);
|
||||
entity.setHasLinks(links.isEmpty() == false);
|
||||
|
||||
} else {
|
||||
|
||||
populateResourceIntoEntity(theResource, entity);
|
||||
entity.setUpdated(new Date());
|
||||
entity.setLanguage(theResource.getLanguage().getValue());
|
||||
|
||||
}
|
||||
|
||||
if (entity.getId() == null) {
|
||||
|
@ -922,59 +990,63 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity = myEntityManager.merge(entity);
|
||||
}
|
||||
|
||||
if (entity.isParamsStringPopulated()) {
|
||||
for (ResourceIndexedSearchParamString next : paramsString) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamString next : stringParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
if (thePerformIndexing) {
|
||||
|
||||
if (entity.isParamsTokenPopulated()) {
|
||||
for (ResourceIndexedSearchParamToken next : paramsToken) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsStringPopulated()) {
|
||||
for (ResourceIndexedSearchParamString next : paramsString) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamString next : stringParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamToken next : tokenParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsNumberPopulated()) {
|
||||
for (ResourceIndexedSearchParamNumber next : paramsNumber) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsTokenPopulated()) {
|
||||
for (ResourceIndexedSearchParamToken next : paramsToken) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamToken next : tokenParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamNumber next : numberParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsQuantityPopulated()) {
|
||||
for (ResourceIndexedSearchParamQuantity next : paramsQuantity) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsNumberPopulated()) {
|
||||
for (ResourceIndexedSearchParamNumber next : paramsNumber) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamNumber next : numberParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamQuantity next : quantityParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsDatePopulated()) {
|
||||
for (ResourceIndexedSearchParamDate next : paramsDate) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsQuantityPopulated()) {
|
||||
for (ResourceIndexedSearchParamQuantity next : paramsQuantity) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamQuantity next : quantityParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamDate next : dateParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isHasLinks()) {
|
||||
for (ResourceLink next : resourceLinks) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsDatePopulated()) {
|
||||
for (ResourceIndexedSearchParamDate next : paramsDate) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ResourceLink next : links) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
for (ResourceIndexedSearchParamDate next : dateParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isHasLinks()) {
|
||||
for (ResourceLink next : resourceLinks) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceLink next : links) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
} // if thePerformIndexing
|
||||
|
||||
myEntityManager.flush();
|
||||
|
||||
|
@ -985,4 +1057,17 @@ public abstract class BaseFhirDao implements IDao {
|
|||
return entity;
|
||||
}
|
||||
|
||||
protected static String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,11 +20,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -36,27 +33,14 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
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.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
|
||||
public abstract class BaseFhirSystemDao<T> extends BaseFhirDao implements IFhirSystemDao<T> {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirSystemDao.class);
|
||||
|
||||
|
@ -82,53 +66,6 @@ public abstract class BaseFhirSystemDao<T> extends BaseFhirDao implements IFhirS
|
|||
return myEntityManager.find(ResourceTable.class, candidateMatches.iterator().next());
|
||||
}
|
||||
|
||||
protected Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
String paramName = next.getName();
|
||||
String qualifier = null;
|
||||
for (int i = 0; i < paramMap.size(); i++) {
|
||||
switch (paramName.charAt(i)) {
|
||||
case '.':
|
||||
case ':':
|
||||
qualifier = paramName.substring(i);
|
||||
paramName = paramName.substring(0, i);
|
||||
i = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, next.getValue());
|
||||
nameToParamLists.put(paramName, paramList);
|
||||
}
|
||||
|
||||
for (String nextParamName : nameToParamLists.keySet()) {
|
||||
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
|
||||
if (paramDef == null) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
List<QualifiedParamList> paramList = nameToParamLists.get(nextParamName);
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(paramDef, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
}
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider history(Date theSince) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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 ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
||||
public class DaoMethodOutcome extends MethodOutcome {
|
||||
|
||||
private ResourceTable myEntity;
|
||||
private IResource myResource;
|
||||
|
||||
public ResourceTable getEntity() {
|
||||
return myEntity;
|
||||
}
|
||||
|
||||
public IResource getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome setCreated(Boolean theCreated) {
|
||||
super.setCreated(theCreated);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaoMethodOutcome setEntity(ResourceTable theEntity) {
|
||||
myEntity = theEntity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaoMethodOutcome setResource(IResource theResource) {
|
||||
myResource = theResource;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -20,229 +20,516 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryTransactionResponse;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirSystemDaoDstu2 extends BaseFhirSystemDao<Bundle> {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2.class);
|
||||
|
||||
private UrlParts parseUrl(String theAction, String theUrl) {
|
||||
UrlParts retVal = new UrlParts();
|
||||
|
||||
//@formatter:off
|
||||
/*
|
||||
* We assume that the URL passed in is in one of the following forms:
|
||||
* [Resource Type]?[Search Params]
|
||||
* [Resource Type]/[Resource ID]
|
||||
* [Resource Type]/[Resource ID]/_history/[Version ID]
|
||||
*/
|
||||
//@formatter:on
|
||||
int nextStart = 0;
|
||||
boolean nextIsHistory = false;
|
||||
|
||||
for (int idx = 0; idx < theUrl.length(); idx++) {
|
||||
char nextChar = theUrl.charAt(idx);
|
||||
boolean atEnd = (idx + 1) == theUrl.length();
|
||||
if (nextChar == '?' || nextChar == '/' || atEnd) {
|
||||
int endIdx = atEnd ? idx + 1 : idx;
|
||||
String nextSubstring = theUrl.substring(nextStart, endIdx);
|
||||
if (retVal.getResourceType() == null) {
|
||||
retVal.setResourceType(nextSubstring);
|
||||
} else if (retVal.getResourceId() == null) {
|
||||
retVal.setResourceId(nextSubstring);
|
||||
} else if (nextIsHistory) {
|
||||
retVal.setVersionId(nextSubstring);
|
||||
} else {
|
||||
if (nextSubstring.equals(Constants.URL_TOKEN_HISTORY)) {
|
||||
nextIsHistory = true;
|
||||
} else {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
if (nextChar == '?') {
|
||||
if (theUrl.length() > idx + 1) {
|
||||
retVal.setParams(theUrl.substring(idx + 1, theUrl.length()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
nextStart = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resType = getContext().getResourceDefinition(retVal.getResourceType());
|
||||
IFhirResourceDao<? extends IResource> dao = null;
|
||||
if (resType != null) {
|
||||
dao = getDao(resType.getImplementingClass());
|
||||
}
|
||||
if (dao == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
retVal.setDao(dao);
|
||||
|
||||
if (retVal.getResourceId() == null && retVal.getParams() == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Bundle transaction(Bundle theResources) {
|
||||
ourLog.info("Beginning transaction with {} resources", theResources.getEntry().size());
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// Set<IdDt> allIds = new HashSet<IdDt>();
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource res = theResources.get(i);
|
||||
// if (res.getId().hasIdPart() && !res.getId().hasResourceType()) {
|
||||
// res.setId(new IdDt(toResourceName(res.getClass()), res.getId().getIdPart()));
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||
// */
|
||||
// if (res.getId().hasResourceType() && res.getId().hasIdPart()) {
|
||||
// IdDt nextId = res.getId().toUnqualifiedVersionless();
|
||||
// if (!allIds.add(nextId)) {
|
||||
// throw new InvalidRequestException("Transaction bundle contains multiple resources with ID: " + nextId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// FhirTerser terser = getContext().newTerser();
|
||||
//
|
||||
// int creations = 0;
|
||||
// int updates = 0;
|
||||
//
|
||||
// Map<IdDt, IdDt> idConversions = new HashMap<IdDt, IdDt>();
|
||||
//
|
||||
// List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();
|
||||
//
|
||||
// List<IResource> retVal = new ArrayList<IResource>();
|
||||
// OperationOutcome oo = new OperationOutcome();
|
||||
// retVal.add(oo);
|
||||
//
|
||||
// for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
|
||||
// IResource nextResource = theResources.get(resourceIdx);
|
||||
//
|
||||
// IdDt nextId = nextResource.getId();
|
||||
// if (nextId == null) {
|
||||
// nextId = new IdDt();
|
||||
// }
|
||||
//
|
||||
// String resourceName = toResourceName(nextResource);
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationIn = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(nextResource);
|
||||
// if (nextResouceOperationIn == null && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
|
||||
// nextResouceOperationIn = BundleEntryTransactionOperationEnum.DELETE;
|
||||
// }
|
||||
//
|
||||
// String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
|
||||
// Set<Long> candidateMatches = null;
|
||||
// if (StringUtils.isNotBlank(matchUrl)) {
|
||||
// candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
|
||||
// }
|
||||
//
|
||||
// ResourceTable entity;
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// entity = null;
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE || nextResouceOperationIn == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// if (candidateMatches == null || candidateMatches.size() == 0) {
|
||||
// if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationFailedNoId", nextResouceOperationIn.name()));
|
||||
// }
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// if (entity == null) {
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE) {
|
||||
// ourLog.debug("Attempting to UPDATE resource with unknown ID '{}', will CREATE instead", nextId);
|
||||
// } else if (candidateMatches == null) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationFailedUnknownId", nextResouceOperationIn.name(), nextId));
|
||||
// } else {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(nextResource);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// } else if (candidateMatches.size() == 1) {
|
||||
// entity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// } else {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationWithMultipleMatchFailure", nextResouceOperationIn.name(), matchUrl, candidateMatches.size()));
|
||||
// }
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.NOOP) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "incomingNoopInTransaction"));
|
||||
// } else if (nextId.isEmpty()) {
|
||||
// entity = null;
|
||||
// } else {
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// }
|
||||
//
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationOut;
|
||||
// if (entity == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.CREATE;
|
||||
// entity = toEntity(nextResource);
|
||||
// if (nextId.isEmpty() == false && nextId.getIdPart().startsWith("cid:")) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}], will replace with server assigned ID", nextId.getIdPart());
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// if (nextId.isEmpty() == false) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID", nextId.getIdPart());
|
||||
// }
|
||||
// if (candidateMatches != null) {
|
||||
// if (candidateMatches.size() == 1) {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// BaseHasResource existingEntity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// IResource existing = (IResource) toResource(existingEntity);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(existing, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(existing);
|
||||
// continue;
|
||||
// }
|
||||
// if (candidateMatches.size() > 1) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationWithMultipleMatchFailure", BundleEntryTransactionOperationEnum.CREATE.name(), matchUrl, candidateMatches.size()));
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// createForcedIdIfNeeded(entity, nextId);
|
||||
// }
|
||||
// myEntityManager.persist(entity);
|
||||
// if (entity.getForcedId() != null) {
|
||||
// myEntityManager.persist(entity.getForcedId());
|
||||
// }
|
||||
// creations++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
|
||||
// } else {
|
||||
// nextResouceOperationOut = nextResouceOperationIn;
|
||||
// if (nextResouceOperationOut == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.UPDATE;
|
||||
// }
|
||||
// updates++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
|
||||
// }
|
||||
//
|
||||
// persistedResources.add(entity);
|
||||
// retVal.add(nextResource);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, nextResouceOperationOut);
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Flushing transaction to database");
|
||||
// myEntityManager.flush();
|
||||
//
|
||||
// for (int i = 0; i < persistedResources.size(); i++) {
|
||||
// ResourceTable entity = persistedResources.get(i);
|
||||
//
|
||||
// String resourceName = toResourceName(theResources.get(i));
|
||||
// IdDt nextId = theResources.get(i).getId();
|
||||
//
|
||||
// IdDt newId;
|
||||
//
|
||||
// if (entity == null) {
|
||||
// newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
|
||||
// } else {
|
||||
// newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
// }
|
||||
//
|
||||
// if (nextId == null || nextId.isEmpty()) {
|
||||
// ourLog.info("Transaction resource (with no preexisting ID) has been assigned new ID[{}]", nextId, newId);
|
||||
// } else {
|
||||
// if (nextId.toUnqualifiedVersionless().equals(newId)) {
|
||||
// ourLog.info("Transaction resource ID[{}] is being updated", newId);
|
||||
// } else {
|
||||
// if (!nextId.getIdPart().startsWith("#")) {
|
||||
// nextId = new IdDt(resourceName + '/' + nextId.getIdPart());
|
||||
// ourLog.info("Transaction resource ID[{}] has been assigned new ID[{}]", nextId, newId);
|
||||
// idConversions.put(nextId, newId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// for (IResource nextResource : theResources) {
|
||||
// List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||
// for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||
// IdDt nextId = nextRef.getReference();
|
||||
// if (idConversions.containsKey(nextId)) {
|
||||
// IdDt newId = idConversions.get(nextId);
|
||||
// ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||
// nextRef.setReference(newId);
|
||||
// } else {
|
||||
// ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Re-flushing updated resource references and extracting search criteria");
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource resource = theResources.get(i);
|
||||
// ResourceTable table = persistedResources.get(i);
|
||||
// if (table == null) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
|
||||
// Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
// if (deletedInstantOrNull == null && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(resource) == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// deletedTimestampOrNull = new Date();
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
|
||||
// }
|
||||
//
|
||||
// updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull);
|
||||
// }
|
||||
//
|
||||
// long delay = System.currentTimeMillis() - start;
|
||||
// ourLog.info("Transaction completed in {}ms with {} creations and {} updates", new Object[] { delay, creations, updates });
|
||||
//
|
||||
// oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in " + delay + "ms with " + creations + " creations and " + updates + " updates");
|
||||
//
|
||||
// notifyWriteCompleted();
|
||||
Set<IdDt> allIds = new HashSet<IdDt>();
|
||||
Map<IdDt, IdDt> idSubstitutions = new HashMap<IdDt, IdDt>();
|
||||
Map<IdDt, DaoMethodOutcome> idToPersistedOutcome = new HashMap<IdDt, DaoMethodOutcome>();
|
||||
|
||||
return null;
|
||||
Bundle response = new Bundle();
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
response.addEntry().setResource(oo);
|
||||
|
||||
for (int i = 0; i < theResources.getEntry().size(); i++) {
|
||||
Entry nextEntry = theResources.getEntry().get(i);
|
||||
IResource res = nextEntry.getResource();
|
||||
IdDt nextResourceId = null;
|
||||
if (res != null) {
|
||||
|
||||
nextResourceId = res.getId();
|
||||
if (nextResourceId.hasIdPart() && !nextResourceId.hasResourceType()) {
|
||||
nextResourceId = new IdDt(toResourceName(res.getClass()), nextResourceId.getIdPart());
|
||||
res.setId(nextResourceId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||
*/
|
||||
if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
|
||||
IdDt nextId = nextResourceId.toUnqualifiedVersionless();
|
||||
if (!allIds.add(nextId)) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HTTPVerbEnum verb = nextEntry.getTransaction().getMethodElement().getValueAsEnum();
|
||||
if (verb == null) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextEntry.getTransaction().getMethod()));
|
||||
}
|
||||
|
||||
switch (verb) {
|
||||
case POST: {
|
||||
// CREATE
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = getDao(res.getClass());
|
||||
res.setId(null);
|
||||
DaoMethodOutcome outcome;
|
||||
Entry newEntry = response.addEntry();
|
||||
outcome = resourceDao.create(res, nextEntry.getTransaction().getIfNoneExist(), false);
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, newEntry);
|
||||
break;
|
||||
}
|
||||
case DELETE: {
|
||||
// DELETE
|
||||
Entry newEntry = response.addEntry();
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
if (parts.getResourceId() != null) {
|
||||
parts.getDao().delete(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
} else {
|
||||
parts.getDao().deleteByUrl(parts.getResourceType() + '?' + parts.getParams());
|
||||
}
|
||||
|
||||
newEntry.getTransactionResponse().setStatus(Integer.toString(Constants.STATUS_HTTP_204_NO_CONTENT));
|
||||
break;
|
||||
}
|
||||
case PUT: {
|
||||
// UPDATE
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = getDao(res.getClass());
|
||||
|
||||
DaoMethodOutcome outcome;
|
||||
Entry newEntry = response.addEntry();
|
||||
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
if (parts.getResourceId() != null) {
|
||||
res.setId(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
outcome = resourceDao.update(res, null, false);
|
||||
} else {
|
||||
res.setId(null);
|
||||
outcome = resourceDao.update(res, parts.getResourceType() + '?' + parts.getParams(), false);
|
||||
}
|
||||
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, newEntry);
|
||||
break;
|
||||
}
|
||||
case GET: {
|
||||
// SEARCH/READ/VREAD
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = parts.getDao();
|
||||
|
||||
if (parts.getResourceId() != null && parts.getParams() == null) {
|
||||
IResource found;
|
||||
if (parts.getVersionId() != null) {
|
||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||
} else {
|
||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
}
|
||||
EntryTransactionResponse resp = response.addEntry().setResource(found).getTransactionResponse();
|
||||
resp.setLocation(found.getId().toUnqualified().getValue());
|
||||
resp.addEtag(found.getId().getVersionIdPart());
|
||||
} else if (parts.getParams() != null) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(parts.getDao().getResourceType());
|
||||
SearchParameterMap params = translateMatchUrl(url, def);
|
||||
IBundleProvider bundle = parts.getDao().search(params);
|
||||
|
||||
Bundle searchBundle = new Bundle();
|
||||
searchBundle.setTotal(bundle.size());
|
||||
|
||||
int configuredMax = 100; // this should probably be configurable or something
|
||||
if (bundle.size() > configuredMax) {
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.WARNING).setDetails("Search nested within transaction found more than " + configuredMax + " matches, but paging is not supported in nested transactions");
|
||||
}
|
||||
List<IResource> resourcesToAdd = bundle.getResources(0, Math.min(bundle.size(), configuredMax));
|
||||
for (IResource next : resourcesToAdd) {
|
||||
searchBundle.addEntry().setResource(next);
|
||||
}
|
||||
|
||||
response.addEntry().setResource(searchBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FhirTerser terser = getContext().newTerser();
|
||||
|
||||
// int creations = 0;
|
||||
// int updates = 0;
|
||||
//
|
||||
// Map<IdDt, IdDt> idConversions = new HashMap<IdDt, IdDt>();
|
||||
//
|
||||
// List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();
|
||||
//
|
||||
// List<IResource> retVal = new ArrayList<IResource>();
|
||||
// OperationOutcome oo = new OperationOutcome();
|
||||
// retVal.add(oo);
|
||||
//
|
||||
// for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
|
||||
// IResource nextResource = theResources.get(resourceIdx);
|
||||
//
|
||||
// IdDt nextId = nextResource.getId();
|
||||
// if (nextId == null) {
|
||||
// nextId = new IdDt();
|
||||
// }
|
||||
//
|
||||
// String resourceName = toResourceName(nextResource);
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationIn =
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(nextResource);
|
||||
// if (nextResouceOperationIn == null && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
|
||||
// nextResouceOperationIn = BundleEntryTransactionOperationEnum.DELETE;
|
||||
// }
|
||||
//
|
||||
// String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
|
||||
// Set<Long> candidateMatches = null;
|
||||
// if (StringUtils.isNotBlank(matchUrl)) {
|
||||
// candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
|
||||
// }
|
||||
//
|
||||
// ResourceTable entity;
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// entity = null;
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE || nextResouceOperationIn ==
|
||||
// BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// if (candidateMatches == null || candidateMatches.size() == 0) {
|
||||
// if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationFailedNoId", nextResouceOperationIn.name()));
|
||||
// }
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// if (entity == null) {
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE) {
|
||||
// ourLog.debug("Attempting to UPDATE resource with unknown ID '{}', will CREATE instead", nextId);
|
||||
// } else if (candidateMatches == null) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationFailedUnknownId", nextResouceOperationIn.name(), nextId));
|
||||
// } else {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource,
|
||||
// BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(nextResource);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// } else if (candidateMatches.size() == 1) {
|
||||
// entity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// } else {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationWithMultipleMatchFailure", nextResouceOperationIn.name(), matchUrl,
|
||||
// candidateMatches.size()));
|
||||
// }
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.NOOP) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "incomingNoopInTransaction"));
|
||||
// } else if (nextId.isEmpty()) {
|
||||
// entity = null;
|
||||
// } else {
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// }
|
||||
//
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationOut;
|
||||
// if (entity == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.CREATE;
|
||||
// entity = toEntity(nextResource);
|
||||
// if (nextId.isEmpty() == false && nextId.getIdPart().startsWith("cid:")) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}], will replace with server assigned ID", nextId.getIdPart());
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// if (nextId.isEmpty() == false) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID",
|
||||
// nextId.getIdPart());
|
||||
// }
|
||||
// if (candidateMatches != null) {
|
||||
// if (candidateMatches.size() == 1) {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// BaseHasResource existingEntity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// IResource existing = (IResource) toResource(existingEntity);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(existing, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(existing);
|
||||
// continue;
|
||||
// }
|
||||
// if (candidateMatches.size() > 1) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationWithMultipleMatchFailure", BundleEntryTransactionOperationEnum.CREATE.name(), matchUrl,
|
||||
// candidateMatches.size()));
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// createForcedIdIfNeeded(entity, nextId);
|
||||
// }
|
||||
// myEntityManager.persist(entity);
|
||||
// if (entity.getForcedId() != null) {
|
||||
// myEntityManager.persist(entity.getForcedId());
|
||||
// }
|
||||
// creations++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
|
||||
// } else {
|
||||
// nextResouceOperationOut = nextResouceOperationIn;
|
||||
// if (nextResouceOperationOut == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.UPDATE;
|
||||
// }
|
||||
// updates++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
|
||||
// }
|
||||
//
|
||||
// persistedResources.add(entity);
|
||||
// retVal.add(nextResource);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, nextResouceOperationOut);
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Flushing transaction to database");
|
||||
// myEntityManager.flush();
|
||||
//
|
||||
// for (int i = 0; i < persistedResources.size(); i++) {
|
||||
// ResourceTable entity = persistedResources.get(i);
|
||||
//
|
||||
// String resourceName = toResourceName(theResources.get(i));
|
||||
// IdDt nextId = theResources.get(i).getId();
|
||||
//
|
||||
// IdDt newId;
|
||||
//
|
||||
// if (entity == null) {
|
||||
// newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
|
||||
// } else {
|
||||
// newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
// }
|
||||
//
|
||||
// if (nextId == null || nextId.isEmpty()) {
|
||||
// ourLog.info("Transaction resource (with no preexisting ID) has been assigned new ID[{}]", nextId, newId);
|
||||
// } else {
|
||||
// if (nextId.toUnqualifiedVersionless().equals(newId)) {
|
||||
// ourLog.info("Transaction resource ID[{}] is being updated", newId);
|
||||
// } else {
|
||||
// if (!nextId.getIdPart().startsWith("#")) {
|
||||
// nextId = new IdDt(resourceName + '/' + nextId.getIdPart());
|
||||
// ourLog.info("Transaction resource ID[{}] has been assigned new ID[{}]", nextId, newId);
|
||||
// idConversions.put(nextId, newId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
for (DaoMethodOutcome nextOutcome : idToPersistedOutcome.values()) {
|
||||
IResource nextResource = nextOutcome.getResource();
|
||||
if (nextResource == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||
for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||
IdDt nextId = nextRef.getReference();
|
||||
if (idSubstitutions.containsKey(nextId)) {
|
||||
IdDt newId = idSubstitutions.get(nextId);
|
||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||
nextRef.setReference(newId);
|
||||
} else {
|
||||
ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
|
||||
}
|
||||
}
|
||||
|
||||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false);
|
||||
}
|
||||
//
|
||||
// ourLog.info("Re-flushing updated resource references and extracting search criteria");
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource resource = theResources.get(i);
|
||||
// ResourceTable table = persistedResources.get(i);
|
||||
// if (table == null) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
|
||||
// Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
// if (deletedInstantOrNull == null && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(resource) ==
|
||||
// BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// deletedTimestampOrNull = new Date();
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
|
||||
// }
|
||||
//
|
||||
// updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull);
|
||||
// }
|
||||
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
ourLog.info("Transaction completed in {}ms", new Object[]{delay});
|
||||
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in " + delay + "ms");
|
||||
|
||||
notifyWriteCompleted();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private void handleTransactionCreateOrUpdateOutcome(Map<IdDt, IdDt> idSubstitutions, Map<IdDt, DaoMethodOutcome> idToPersistedOutcome, IdDt nextResourceId, DaoMethodOutcome outcome, Entry newEntry) {
|
||||
IdDt newId = outcome.getId().toUnqualifiedVersionless();
|
||||
if (newId.equals(nextResourceId) == false) {
|
||||
idSubstitutions.put(nextResourceId, newId);
|
||||
}
|
||||
idToPersistedOutcome.put(newId, outcome);
|
||||
if (outcome.getCreated().booleanValue()) {
|
||||
newEntry.getTransactionResponse().setStatus(Long.toString(Constants.STATUS_HTTP_201_CREATED));
|
||||
} else {
|
||||
newEntry.getTransactionResponse().setStatus(Long.toString(Constants.STATUS_HTTP_200_OK));
|
||||
}
|
||||
newEntry.getTransactionResponse().setLocation(outcome.getId().toUnqualified().getValue());
|
||||
newEntry.getTransactionResponse().addEtag().setValue(outcome.getId().getVersionIdPart());
|
||||
}
|
||||
|
||||
private String extractTransactionUrlOrThrowException(Entry nextEntry, HTTPVerbEnum verb) {
|
||||
String url = nextEntry.getTransaction().getUrl();
|
||||
if (isBlank(url)) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionMissingUrl", verb.name()));
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private static class UrlParts {
|
||||
private IFhirResourceDao<? extends IResource> myDao;
|
||||
private String myParams;
|
||||
private String myResourceId;
|
||||
private String myResourceType;
|
||||
private String myVersionId;
|
||||
|
||||
public IFhirResourceDao<? extends IResource> getDao() {
|
||||
return myDao;
|
||||
}
|
||||
|
||||
public void setVersionId(String theVersionId) {
|
||||
myVersionId = theVersionId;
|
||||
}
|
||||
|
||||
public String getVersionId() {
|
||||
return myVersionId;
|
||||
}
|
||||
|
||||
public String getParams() {
|
||||
return myParams;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setDao(IFhirResourceDao<? extends IResource> theDao) {
|
||||
myDao = theDao;
|
||||
}
|
||||
|
||||
public void setParams(String theParams) {
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
public void setResourceId(String theResourceId) {
|
||||
myResourceId = theResourceId;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
|
@ -37,9 +36,19 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
void addTag(IdDt theId, String theScheme, String theTerm, String theLabel);
|
||||
|
||||
MethodOutcome create(T theResource);
|
||||
DaoMethodOutcome create(T theResource);
|
||||
|
||||
MethodOutcome delete(IdDt theResource);
|
||||
DaoMethodOutcome create(T theResource, String theIfNoneExist);
|
||||
|
||||
/**
|
||||
* @param thePerformIndexing Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||
* won't be indexed and searches won't work.
|
||||
*/
|
||||
DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing);
|
||||
|
||||
DaoMethodOutcome delete(IdDt theResource);
|
||||
|
||||
DaoMethodOutcome deleteByUrl(String theString);
|
||||
|
||||
TagList getAllResourceTags();
|
||||
|
||||
|
@ -49,20 +58,27 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
IBundleProvider history(Date theSince);
|
||||
|
||||
IBundleProvider history(IdDt theId,Date theSince);
|
||||
IBundleProvider history(IdDt theId, Date theSince);
|
||||
|
||||
IBundleProvider history(Long theId, Date theSince);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param theId
|
||||
* @return
|
||||
* @throws ResourceNotFoundException If the ID is not known to the server
|
||||
* @throws ResourceNotFoundException
|
||||
* If the ID is not known to the server
|
||||
*/
|
||||
T read(IdDt theId);
|
||||
|
||||
BaseHasResource readEntity(IdDt theId);
|
||||
|
||||
/**
|
||||
* @param theCheckForForcedId If true, this method should fail if the requested ID contains a numeric PID which exists, but is
|
||||
* obscured by a "forced ID" so should not exist as far as the outside world is concerned.
|
||||
*/
|
||||
BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId);
|
||||
|
||||
void removeTag(IdDt theId, String theScheme, String theTerm);
|
||||
|
||||
IBundleProvider search(Map<String, IQueryParameterType> theParams);
|
||||
|
@ -75,15 +91,17 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
Set<Long> searchForIds(String theParameterName, IQueryParameterType theValue);
|
||||
|
||||
MethodOutcome update(T theResource, IdDt theId);
|
||||
|
||||
Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams);
|
||||
|
||||
DaoMethodOutcome update(T theResource);
|
||||
|
||||
DaoMethodOutcome update(T theResource, String theMatchUrl);
|
||||
|
||||
/**
|
||||
* @param theCheckForForcedId If true, this method should fail if the requested ID contains
|
||||
* a numeric PID which exists, but is obscured by a "forced ID" so should not exist as
|
||||
* far as the outside world is concerned.
|
||||
* @param thePerformIndexing
|
||||
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||
* won't be indexed and searches won't work.
|
||||
*/
|
||||
BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId);
|
||||
|
||||
DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing);
|
||||
|
||||
}
|
||||
|
|
|
@ -32,9 +32,15 @@ import javax.persistence.OneToOne;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
//@formatter:off
|
||||
@Entity()
|
||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = { @UniqueConstraint(name = "IDX_FORCEDID", columnNames = { "FORCED_ID" }) })
|
||||
@NamedQueries(@NamedQuery(name = "Q_GET_FORCED_ID", query = "SELECT f FROM ForcedId f WHERE myForcedId = :ID"))
|
||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "IDX_FORCEDID", columnNames = {"FORCED_ID"})
|
||||
})
|
||||
@NamedQueries(value = {
|
||||
@NamedQuery(name = "Q_GET_FORCED_ID", query = "SELECT f FROM ForcedId f WHERE myForcedId = :ID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ForcedId {
|
||||
|
||||
public static final int MAX_FORCED_ID_LENGTH = 100;
|
||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
|
@ -44,11 +45,11 @@ import javax.servlet.http.HttpServletRequest;
|
|||
public class JpaConformanceProviderDstu1 extends ServerConformanceProvider {
|
||||
|
||||
private String myImplementationDescription;
|
||||
private IFhirSystemDao mySystemDao;
|
||||
private IFhirSystemDao<List<IResource>> mySystemDao;
|
||||
private volatile Conformance myCachedValue;
|
||||
private RestfulServer myRestfulServer;
|
||||
|
||||
public JpaConformanceProviderDstu1(RestfulServer theRestfulServer, IFhirSystemDao theSystemDao) {
|
||||
public JpaConformanceProviderDstu1(RestfulServer theRestfulServer, IFhirSystemDao<List<IResource>> theSystemDao) {
|
||||
super(theRestfulServer);
|
||||
myRestfulServer = theRestfulServer;
|
||||
mySystemDao = theSystemDao;
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResource;
|
||||
|
@ -44,11 +45,11 @@ import ca.uhn.fhir.util.ExtensionConstants;
|
|||
public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
||||
|
||||
private String myImplementationDescription;
|
||||
private IFhirSystemDao mySystemDao;
|
||||
private IFhirSystemDao<Bundle> mySystemDao;
|
||||
private volatile Conformance myCachedValue;
|
||||
private RestfulServer myRestfulServer;
|
||||
|
||||
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao theSystemDao) {
|
||||
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao<Bundle> theSystemDao) {
|
||||
super(theRestfulServer);
|
||||
myRestfulServer = theRestfulServer;
|
||||
mySystemDao = theSystemDao;
|
||||
|
|
|
@ -162,13 +162,12 @@ public class JpaResourceProvider<T extends IResource> extends BaseJpaProvider im
|
|||
public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId) {
|
||||
startRequest(theRequest);
|
||||
try {
|
||||
return myDao.update(theResource, theId);
|
||||
theResource.setId(theId);
|
||||
return myDao.update(theResource);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
|
||||
theResource.setId(theId);
|
||||
MethodOutcome retVal = myDao.create(theResource);
|
||||
retVal.setCreated(true);
|
||||
return retVal;
|
||||
return myDao.create(theResource);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -40,6 +30,7 @@ import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
|||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Device;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Encounter;
|
||||
|
@ -47,7 +38,9 @@ import ca.uhn.fhir.model.dstu2.resource.Location;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
|
@ -65,8 +58,10 @@ import ca.uhn.fhir.rest.param.ReferenceParam;
|
|||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
@ -84,6 +79,150 @@ public class FhirResourceDaoTest {
|
|||
private static IFhirResourceDao<Organization> ourOrganizationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
|
||||
@Test
|
||||
public void testCreateDuplicateIdFails() {
|
||||
String methodName = "testCreateDuplocateIdFailsText";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
try {
|
||||
ourPatientDao.create(p);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("Can not create entity with ID[" + methodName + "], a resource with this ID already exists"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByUrl() {
|
||||
String methodName = "testUpdateByUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
|
||||
ourPatientDao.update(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
p = ourPatientDao.read(id.toVersionless());
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateNumericIdFails() {
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/123");
|
||||
try {
|
||||
ourPatientDao.create(p);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Can not create entity with ID[123], this server does not allow clients to assign numeric IDs"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteWithMatchUrl() {
|
||||
String methodName = "testDeleteWithMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
ourPatientDao.deleteByUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
IBundleProvider history = ourPatientDao.history(id, null);
|
||||
assertEquals(2, history.size());
|
||||
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
|
||||
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1, 1).get(0)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateWithIfNoneExist() {
|
||||
String methodName = "testCreateWithIfNoneExist";
|
||||
MethodOutcome results;
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
assertEquals(id.getIdPart(), results.getId().getIdPart());
|
||||
assertFalse(results.getCreated().booleanValue());
|
||||
|
||||
// Now create a second one
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName + "DOESNTEXIST");
|
||||
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName + "DOESNTEXIST");
|
||||
assertNotEquals(id.getIdPart(), results.getId().getIdPart());
|
||||
assertTrue(results.getCreated().booleanValue());
|
||||
|
||||
// Now try to create one with the original match URL and it should fail
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
try {
|
||||
ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("Failed to CREATE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChoiceParamConcept() {
|
||||
Observation o1 = new Observation();
|
||||
|
@ -216,7 +355,7 @@ public class FhirResourceDaoTest {
|
|||
public void testDatePeriodParamStartAndEnd() {
|
||||
{
|
||||
Encounter enc = new Encounter();
|
||||
enc.addIdentifier().setSystem("testDatePeriodParam").setValue( "03");
|
||||
enc.addIdentifier().setSystem("testDatePeriodParam").setValue("03");
|
||||
enc.getPeriod().getStartElement().setValueAsString("2001-01-02");
|
||||
enc.getPeriod().getEndElement().setValueAsString("2001-01-03");
|
||||
ourEncounterDao.create(enc);
|
||||
|
@ -329,7 +468,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = ourPatientDao.read(id2);
|
||||
patient.addIdentifier().setSystem("ZZZZZZZ").setValue("ZZZZZZZZZ");
|
||||
id2b = ourPatientDao.update(patient, id2).getId();
|
||||
id2b = ourPatientDao.update(patient).getId();
|
||||
}
|
||||
ourLog.info("ID1:{} ID2:{} ID2b:{}", new Object[] { id1, id2, id2b });
|
||||
|
||||
|
@ -373,7 +512,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testIdParam() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
MethodOutcome outcome = ourPatientDao.create(patient);
|
||||
|
@ -484,11 +623,11 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistResourceLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testPersistResourceLink01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistResourceLink01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testPersistResourceLink02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testPersistResourceLink02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -524,7 +663,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistSearchParamDate() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.setBirthDate(new DateDt("2001-01-01"));
|
||||
|
||||
ourPatientDao.create(patient);
|
||||
|
@ -576,7 +715,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistSearchParams() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001testPersistSearchParams");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001testPersistSearchParams");
|
||||
patient.getGenderElement().setValueAsEnum(AdministrativeGenderEnum.MALE);
|
||||
patient.addName().addFamily("Tester").addGiven("JoetestPersistSearchParams");
|
||||
|
||||
|
@ -641,20 +780,20 @@ public class FhirResourceDaoTest {
|
|||
assertTrue(patients.size() >= 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHistoryByForcedId() {
|
||||
IdDt idv1;
|
||||
IdDt idv2;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testHistoryByForcedId");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistoryByForcedId");
|
||||
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedId");
|
||||
patient.setId("Patient/testHistoryByForcedId");
|
||||
idv1 = ourPatientDao.create(patient).getId();
|
||||
|
||||
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedIdName2");
|
||||
idv2 = ourPatientDao.update(patient, idv1.toUnqualifiedVersionless()).getId();
|
||||
patient.setId(patient.getId().toUnqualifiedVersionless());
|
||||
idv2 = ourPatientDao.update(patient).getId();
|
||||
}
|
||||
|
||||
List<Patient> patients = toList(ourPatientDao.history(idv1.toVersionless(), null));
|
||||
|
@ -676,7 +815,7 @@ public class FhirResourceDaoTest {
|
|||
IdDt id2;
|
||||
{
|
||||
Organization patient = new Organization();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
id2 = ourOrganizationDao.create(patient).getId();
|
||||
}
|
||||
|
||||
|
@ -769,14 +908,14 @@ public class FhirResourceDaoTest {
|
|||
IdDt id1;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("testSearchNameParam01Fam").addGiven("testSearchNameParam01Giv");
|
||||
ResourceMetadataKeyEnum.TITLE.put(patient, "P1TITLE");
|
||||
id1 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("testSearchNameParam02Fam").addGiven("testSearchNameParam02Giv");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -816,12 +955,12 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSearchNumberParam() {
|
||||
Encounter e1 = new Encounter();
|
||||
e1.addIdentifier().setSystem("foo").setValue( "testSearchNumberParam01");
|
||||
e1.addIdentifier().setSystem("foo").setValue("testSearchNumberParam01");
|
||||
e1.getLength().setSystem(BaseFhirDao.UCUM_NS).setCode("min").setValue(4.0 * 24 * 60);
|
||||
IdDt id1 = ourEncounterDao.create(e1).getId();
|
||||
|
||||
Encounter e2 = new Encounter();
|
||||
e2.addIdentifier().setSystem("foo").setValue( "testSearchNumberParam02");
|
||||
e2.addIdentifier().setSystem("foo").setValue("testSearchNumberParam02");
|
||||
e2.getLength().setSystem(BaseFhirDao.UCUM_NS).setCode("year").setValue(2.0);
|
||||
IdDt id2 = ourEncounterDao.create(e2).getId();
|
||||
{
|
||||
|
@ -843,13 +982,13 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSearchResourceLinkWithChain() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChainXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChain01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChainXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChain01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChainXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChain02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChainXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChain02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -881,7 +1020,7 @@ public class FhirResourceDaoTest {
|
|||
|
||||
result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "testSearchResourceLinkWithChainXX")));
|
||||
assertEquals(2, result.size());
|
||||
|
||||
|
||||
result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "|testSearchResourceLinkWithChainXX")));
|
||||
assertEquals(0, result.size());
|
||||
|
||||
|
@ -891,14 +1030,14 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchResourceLinkWithTextLogicalId() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId("testSearchResourceLinkWithTextLogicalId01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalId01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.setId("testSearchResourceLinkWithTextLogicalId02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalId02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -981,13 +1120,13 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchStringParam() {
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1009,7 +1148,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = new Patient();
|
||||
patient.getLanguage().setValue("en_CA");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("testSearchLanguageParam").addGiven("Joe");
|
||||
id1 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
|
@ -1017,7 +1156,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = new Patient();
|
||||
patient.getLanguage().setValue("en_US");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("testSearchLanguageParam").addGiven("John");
|
||||
id2 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
|
@ -1048,13 +1187,13 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchStringParamWithNonNormalized() {
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_h\u00F6ra");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_HORA");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1081,7 +1220,7 @@ public class FhirResourceDaoTest {
|
|||
ourPatientDao.create(patient);
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchTokenParam002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam002");
|
||||
patient.addName().addFamily("Tester").addGiven("testSearchTokenParam2");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
|
@ -1147,14 +1286,14 @@ public class FhirResourceDaoTest {
|
|||
IdDt orgId = ourOrganizationDao.create(org).getId();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludes_P1").addGiven("Joe");
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludes_P2").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1221,7 +1360,7 @@ public class FhirResourceDaoTest {
|
|||
public void testStoreUtf8Characters() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.setName("測試醫院");
|
||||
org.addIdentifier().setSystem("urn:system").setValue( "testStoreUtf8Characters_01");
|
||||
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
||||
IdDt orgId = ourOrganizationDao.create(org).getId();
|
||||
|
||||
Organization returned = ourOrganizationDao.read(orgId);
|
||||
|
@ -1244,14 +1383,14 @@ public class FhirResourceDaoTest {
|
|||
assertThat(orgId.getValue(), endsWith("Organization/testSearchWithIncludesThatHaveTextId_id1/_history/1"));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludesThatHaveTextId_P1").addGiven("Joe");
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludesThatHaveTextId_P2").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1290,23 +1429,23 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSort() {
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF1").addGiven("testSortG1");
|
||||
IdDt id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
// Create out of order
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF3").addGiven("testSortG3");
|
||||
IdDt id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF2").addGiven("testSortG2");
|
||||
IdDt id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
IdDt id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap pm = new SearchParameterMap();
|
||||
|
@ -1367,7 +1506,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testTagsWithCreateAndReadAndSearch() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testTagsWithCreateAndReadAndSearch");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testTagsWithCreateAndReadAndSearch");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
TagList tagList = new TagList();
|
||||
tagList.addTag(null, "Dog", "Puppies");
|
||||
|
@ -1458,7 +1597,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateAndGetHistoryResource() throws InterruptedException {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
MethodOutcome outcome = ourPatientDao.create(patient);
|
||||
|
@ -1477,7 +1616,7 @@ public class FhirResourceDaoTest {
|
|||
Thread.sleep(1000);
|
||||
|
||||
retrieved.getIdentifierFirstRep().setValue("002");
|
||||
MethodOutcome outcome2 = ourPatientDao.update(retrieved, outcome.getId());
|
||||
MethodOutcome outcome2 = ourPatientDao.update(retrieved);
|
||||
assertEquals(outcome.getId().getIdPart(), outcome2.getId().getIdPart());
|
||||
assertNotEquals(outcome.getId().getVersionIdPart(), outcome2.getId().getVersionIdPart());
|
||||
|
||||
|
@ -1521,12 +1660,12 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateMaintainsSearchParams() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsAAA");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue( "testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsBBB");
|
||||
ourPatientDao.create(p2).getId();
|
||||
|
||||
|
@ -1536,7 +1675,7 @@ public class FhirResourceDaoTest {
|
|||
|
||||
// Update the name
|
||||
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
MethodOutcome update2 = ourPatientDao.update(p1, p1id);
|
||||
MethodOutcome update2 = ourPatientDao.update(p1);
|
||||
IdDt p1id2 = update2.getId();
|
||||
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
|
||||
|
@ -1557,21 +1696,23 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testUpdateRejectsInvalidTypes");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateRejectsInvalidTypes");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
|
||||
Organization p2 = new Organization();
|
||||
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
|
||||
try {
|
||||
ourOrganizationDao.update(p2, new IdDt("Organization/" + p1id.getIdPart()));
|
||||
p2.setId(new IdDt("Organization/" + p1id.getIdPart()));
|
||||
ourOrganizationDao.update(p2);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
try {
|
||||
ourOrganizationDao.update(p2, new IdDt("Patient/" + p1id.getIdPart()));
|
||||
p2.setId(new IdDt("Patient/" + p1id.getIdPart()));
|
||||
ourOrganizationDao.update(p2);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
// good
|
||||
|
@ -1589,7 +1730,7 @@ public class FhirResourceDaoTest {
|
|||
assertEquals("ABABA", p1id.getIdPart());
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue( "testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
IdDt p2id = ourPatientDao.create(p2).getId();
|
||||
long p1longId = p2id.getIdPartAsLong() - 1;
|
||||
|
@ -1602,7 +1743,8 @@ public class FhirResourceDaoTest {
|
|||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.update(p1, new IdDt("Patient/" + p1longId));
|
||||
p1.setId(new IdDt("Patient/" + p1longId));
|
||||
ourPatientDao.update(p1);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// good
|
||||
|
@ -1613,13 +1755,14 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testReadForcedIdVersionHistory() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testReadVorcedIdVersionHistory01");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
|
||||
p1.setId("testReadVorcedIdVersionHistory");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
assertEquals("testReadVorcedIdVersionHistory", p1id.getIdPart());
|
||||
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testReadVorcedIdVersionHistory02");
|
||||
IdDt p1idv2 = ourPatientDao.update(p1, p1id).getId();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory02");
|
||||
p1.setId(p1id);
|
||||
IdDt p1idv2 = ourPatientDao.update(p1).getId();
|
||||
assertEquals("testReadVorcedIdVersionHistory", p1idv2.getIdPart());
|
||||
|
||||
assertNotEquals(p1id.getValue(), p1idv2.getValue());
|
||||
|
@ -1652,7 +1795,7 @@ public class FhirResourceDaoTest {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class FhirSystemDaoDstu1Test {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu1Test.class);
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<List<IResource>> ourSystemDao;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
Date start = new Date();
|
||||
Thread.sleep(10);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistory");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid = ourPatientDao.update(patient).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid2 = ourPatientDao.update(patient).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid3 = ourPatientDao.update(patient).getId();
|
||||
|
||||
IBundleProvider values = ourSystemDao.history(start);
|
||||
assertEquals(4, values.size());
|
||||
|
||||
List<IResource> res = values.getResources(0, 4);
|
||||
assertEquals(newpid3, res.get(0).getId());
|
||||
assertEquals(newpid2, res.get(1).getId());
|
||||
assertEquals(newpid, res.get(2).getId());
|
||||
assertEquals(pid.toUnqualifiedVersionless(), res.get(3).getId().toUnqualifiedVersionless());
|
||||
|
||||
Location loc = new Location();
|
||||
loc.getAddress().addLine("AAA");
|
||||
IdDt lid = ourLocationDao.create(loc).getId();
|
||||
|
||||
Location loc2 = new Location();
|
||||
loc2.getAddress().addLine("AAA");
|
||||
ourLocationDao.create(loc2).getId();
|
||||
|
||||
Thread.sleep(2000);
|
||||
|
||||
values = ourLocationDao.history(start);
|
||||
assertEquals(2, values.size());
|
||||
|
||||
values = ourLocationDao.history(lid.getIdPartAsLong(), start);
|
||||
assertEquals(1, values.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0, 1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagOperationss() throws Exception {
|
||||
|
||||
TagList preSystemTl = ourSystemDao.getAllTags();
|
||||
|
||||
TagList tl1 = new TagList();
|
||||
tl1.addTag("testGetAllTagsScheme1", "testGetAllTagsTerm1", "testGetAllTagsLabel1");
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("foo").setValue("testGetAllTags01");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p1, tl1);
|
||||
ourPatientDao.create(p1);
|
||||
|
||||
TagList tl2 = new TagList();
|
||||
tl2.addTag("testGetAllTagsScheme2", "testGetAllTagsTerm2", "testGetAllTagsLabel2");
|
||||
Observation o1 = new Observation();
|
||||
o1.getName().setText("testGetAllTags02");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(o1, tl2);
|
||||
IdDt o1id = ourObservationDao.create(o1).getId();
|
||||
assertTrue(o1id.getVersionIdPart() != null);
|
||||
|
||||
TagList postSystemTl = ourSystemDao.getAllTags();
|
||||
assertEquals(preSystemTl.size() + 2, postSystemTl.size());
|
||||
assertEquals("testGetAllTagsLabel1", postSystemTl.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
|
||||
TagList tags = ourPatientDao.getAllResourceTags();
|
||||
assertEquals("testGetAllTagsLabel1", tags.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
assertNull(tags.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
TagList tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
o1.getResourceMetadata().remove(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
o1.setId(o1id);
|
||||
IdDt o1id2 = ourObservationDao.update(o1).getId();
|
||||
assertTrue(o1id2.getVersionIdPart() != null);
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Remove a tag from a version
|
||||
*/
|
||||
|
||||
ourObservationDao.removeTag(o1id2, "testGetAllTagsScheme2", "testGetAllTagsTerm2");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Add a tag
|
||||
*/
|
||||
ourObservationDao.addTag(o1id2, "testGetAllTagsScheme3", "testGetAllTagsTerm3", "testGetAllTagsLabel3");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3"));
|
||||
assertEquals("testGetAllTagsLabel3", tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoDstu1Test.class.getResourceAsStream("/bundle-dstu1.xml");
|
||||
Bundle bundle = ourFhirContext.newXmlParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(equalToIgnoringCase("74635")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDelete() throws Exception {
|
||||
|
||||
/*
|
||||
* Create 3
|
||||
*/
|
||||
|
||||
List<IResource> res;
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p2);
|
||||
|
||||
Patient p3 = new Patient();
|
||||
p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p3);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(3, results.size());
|
||||
|
||||
/*
|
||||
* Now delete 2
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
List<IResource> existing = results.getResources(0, 3);
|
||||
|
||||
p1 = new Patient();
|
||||
p1.setId(existing.get(0).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Patient();
|
||||
p2.setId(existing.get(1).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(1, results2.size());
|
||||
List<IResource> existing2 = results2.getResources(0, 1);
|
||||
assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
|
||||
ourLocationDao = ourCtx.getBean("myLocationDaoDstu1", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu1", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,680 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public class FhirSystemDaoDstu2Test {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<Bundle> ourSystemDao;
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("Patient/" + id.getIdPart() + "/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
respEntry = resp.getEntry().get(2);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), containsString("Observation/"));
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getTransactionResponse().getLocationElement()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
assertEquals("1", o.getId().getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionReadAndSearch() {
|
||||
String methodName = "testTransactionReadAndSearch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt idv1 = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got id: {}", idv1);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Family Name");
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt idv2 = ourPatientDao.update(p).getId();
|
||||
ourLog.info("Updated patient, got id: {}", idv2);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualified().getValue());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
|
||||
assertEquals(4, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry;
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Patient.class, nextEntry.getResource().getClass());
|
||||
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
assertEquals(Patient.class, nextEntry.getResource().getClass());
|
||||
assertEquals(idv1.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
|
||||
|
||||
nextEntry = resp.getEntry().get(3);
|
||||
assertEquals(Bundle.class, nextEntry.getResource().getClass());
|
||||
|
||||
Bundle respBundle = (Bundle) nextEntry.getResource();
|
||||
assertEquals(1, respBundle.getTotal().intValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithZeroMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
String patientId = respEntry.getTransactionResponse().getLocation();
|
||||
assertThat(patientId, not(endsWith("Patient/" + methodName + "/_history/1")));
|
||||
assertThat(patientId, (endsWith("/_history/1")));
|
||||
assertThat(patientId, (containsString("Patient/")));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
respEntry = resp.getEntry().get(2);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), containsString("Observation/"));
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getTransactionResponse().getLocationElement()));
|
||||
assertEquals(new IdDt(patientId).toUnqualifiedVersionless(), o.getSubject().getReference());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateNoMatchUrl() {
|
||||
String methodName = "testTransactionCreateNoMatchUrl";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
String patientId = respEntry.getTransactionResponse().getLocation();
|
||||
assertThat(patientId, not(containsString("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + "", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
IBundleProvider history = ourPatientDao.history(id, null);
|
||||
assertEquals(2, history.size());
|
||||
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
|
||||
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1, 1).get(0)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertThat(e.getMessage(), containsString("resource with match URL \"Patient?"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteByResourceId() {
|
||||
String methodName = "testTransactionDeleteByResourceId";
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id1 = ourPatientDao.create(p1).getId();
|
||||
ourLog.info("Created patient, got it: {}", id1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p2.setId("Patient/" + methodName);
|
||||
IdDt id2 = ourPatientDao.create(p2).getId();
|
||||
ourLog.info("Created patient, got it: {}", id2);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id1.getIdPart());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id2.getIdPart());
|
||||
|
||||
ourPatientDao.read(id1.toVersionless());
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
assertEquals("204", resp.getEntry().get(1).getTransactionResponse().getStatus());
|
||||
assertEquals("204", resp.getEntry().get(2).getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id1.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithZeroMatch";
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteNoMatchUrl() {
|
||||
String methodName = "testTransactionDeleteNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle res = ourSystemDao.transaction(request);
|
||||
assertEquals(2, res.getEntry().size());
|
||||
|
||||
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + "", res.getEntry().get(1).getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
request.addEntry().setResource(patient1).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
request.addEntry().setResource(patient2).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
ourSystemDao.transaction(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithOneMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("200", nextEntry.getTransactionResponse().getStatus());
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("" + Constants.STATUS_HTTP_200_OK, nextEntry.getTransactionResponse().getStatus());
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(emptyString()));
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
o = ourObservationDao.read(new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithTwoMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId(id);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference(id);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(containsString("test")));
|
||||
assertNotEquals(id.toVersionless(), new IdDt(nextEntry.getTransactionResponse().getLocation()).toVersionless());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("" + Constants.STATUS_HTTP_201_CREATED, nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
o = ourObservationDao.read(new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoMatchUrl() {
|
||||
String methodName = "testTransactionUpdateNoMatchUrl";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient/" + id.getIdPart());
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("200", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), (containsString("test")));
|
||||
assertEquals(id.toVersionless(), new IdDt(nextEntry.getTransactionResponse().getLocation()).toVersionless());
|
||||
assertNotEquals(id, new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), endsWith("/_history/2"));
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
assertEquals("" + Constants.STATUS_HTTP_201_CREATED, nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
o = ourObservationDao.read(new IdDt(resp.getEntry().get(2).getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Issue #55
|
||||
// */
|
||||
// @Test
|
||||
// public void testTransactionWithCidIds() throws Exception {
|
||||
// Bundle request = new Bundle();
|
||||
//
|
||||
// Patient p1 = new Patient();
|
||||
// p1.setId("cid:patient1");
|
||||
// p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
// res.add(p1);
|
||||
//
|
||||
// Observation o1 = new Observation();
|
||||
// o1.setId("cid:observation1");
|
||||
// o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
// o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
// res.add(o1);
|
||||
//
|
||||
// Observation o2 = new Observation();
|
||||
// o2.setId("cid:observation2");
|
||||
// o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
// o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
// res.add(o2);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
// assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
// assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
//
|
||||
// assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
// assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testTransactionWithDelete() throws Exception {
|
||||
// Bundle request = new Bundle();
|
||||
//
|
||||
// /*
|
||||
// * Create 3
|
||||
// */
|
||||
//
|
||||
// List<IResource> res;
|
||||
// res = new ArrayList<IResource>();
|
||||
//
|
||||
// Patient p1 = new Patient();
|
||||
// p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p1);
|
||||
//
|
||||
// Patient p2 = new Patient();
|
||||
// p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p2);
|
||||
//
|
||||
// Patient p3 = new Patient();
|
||||
// p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p3);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// /*
|
||||
// * Verify
|
||||
// */
|
||||
//
|
||||
// IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system",
|
||||
// "testTransactionWithDelete"));
|
||||
// assertEquals(3, results.size());
|
||||
//
|
||||
// /*
|
||||
// * Now delete 2
|
||||
// */
|
||||
//
|
||||
// request = new Bundle();
|
||||
// res = new ArrayList<IResource>();
|
||||
// List<IResource> existing = results.getResources(0, 3);
|
||||
//
|
||||
// p1 = new Patient();
|
||||
// p1.setId(existing.get(0).getId());
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
// res.add(p1);
|
||||
//
|
||||
// p2 = new Patient();
|
||||
// p2.setId(existing.get(1).getId());
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
// res.add(p2);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// /*
|
||||
// * Verify
|
||||
// */
|
||||
//
|
||||
// IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system",
|
||||
// "testTransactionWithDelete"));
|
||||
// assertEquals(1, results2.size());
|
||||
// List<IResource> existing2 = results2.getResources(0, 1);
|
||||
// assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
//
|
||||
// }
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
assertEquals(FhirVersionEnum.DSTU2, ourFhirContext.getVersion().getVersion());
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,899 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public class FhirSystemDaoTest {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoTest.class);
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<List<IResource>> ourSystemDao;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
Date start = new Date();
|
||||
Thread.sleep(10);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistory");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid2 = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid3 = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
IBundleProvider values = ourSystemDao.history(start);
|
||||
assertEquals(4, values.size());
|
||||
|
||||
List<IResource> res = values.getResources(0, 4);
|
||||
assertEquals(newpid3, res.get(0).getId());
|
||||
assertEquals(newpid2, res.get(1).getId());
|
||||
assertEquals(newpid, res.get(2).getId());
|
||||
assertEquals(pid.toUnqualifiedVersionless(), res.get(3).getId().toUnqualifiedVersionless());
|
||||
|
||||
Location loc = new Location();
|
||||
loc.getAddress().addLine("AAA");
|
||||
IdDt lid = ourLocationDao.create(loc).getId();
|
||||
|
||||
Location loc2 = new Location();
|
||||
loc2.getAddress().addLine("AAA");
|
||||
ourLocationDao.create(loc2).getId();
|
||||
|
||||
Thread.sleep(2000);
|
||||
|
||||
values = ourLocationDao.history(start);
|
||||
assertEquals(2, values.size());
|
||||
|
||||
values = ourLocationDao.history(lid.getIdPartAsLong(), start);
|
||||
assertEquals(1, values.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0, 1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagOperationss() throws Exception {
|
||||
|
||||
TagList preSystemTl = ourSystemDao.getAllTags();
|
||||
|
||||
TagList tl1 = new TagList();
|
||||
tl1.addTag("testGetAllTagsScheme1", "testGetAllTagsTerm1", "testGetAllTagsLabel1");
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("foo").setValue("testGetAllTags01");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p1, tl1);
|
||||
ourPatientDao.create(p1);
|
||||
|
||||
TagList tl2 = new TagList();
|
||||
tl2.addTag("testGetAllTagsScheme2", "testGetAllTagsTerm2", "testGetAllTagsLabel2");
|
||||
Observation o1 = new Observation();
|
||||
o1.getName().setText("testGetAllTags02");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(o1, tl2);
|
||||
IdDt o1id = ourObservationDao.create(o1).getId();
|
||||
assertTrue(o1id.getVersionIdPart() != null);
|
||||
|
||||
TagList postSystemTl = ourSystemDao.getAllTags();
|
||||
assertEquals(preSystemTl.size() + 2, postSystemTl.size());
|
||||
assertEquals("testGetAllTagsLabel1", postSystemTl.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
|
||||
TagList tags = ourPatientDao.getAllResourceTags();
|
||||
assertEquals("testGetAllTagsLabel1", tags.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
assertNull(tags.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
TagList tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
o1.getResourceMetadata().remove(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
IdDt o1id2 = ourObservationDao.update(o1, o1id).getId();
|
||||
assertTrue(o1id2.getVersionIdPart() != null);
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Remove a tag from a version
|
||||
*/
|
||||
|
||||
ourObservationDao.removeTag(o1id2, "testGetAllTagsScheme2", "testGetAllTagsTerm2");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Add a tag
|
||||
*/
|
||||
ourObservationDao.addTag(o1id2, "testGetAllTagsScheme3", "testGetAllTagsTerm3", "testGetAllTagsLabel3");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3"));
|
||||
assertEquals("testGetAllTagsLabel3", tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.NOOP, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id, p.getId());
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateNoMatchUrl() {
|
||||
String methodName = "testTransactionCreateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
p = (Patient) resp.get(1);
|
||||
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "ZZZ");
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id2 = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), (containsString("test")));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
assertEquals(id2.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id2, p.getId());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
Patient found = ourPatientDao.read(id);
|
||||
assertEquals(id, found.getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteNoMatchUrl() {
|
||||
String methodName = "testTransactionDeleteNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(p).getValue());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
// @Test TODO: re-enable
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoTest.class.getResourceAsStream("/bundle.json");
|
||||
Bundle bundle = ourFhirContext.newJsonParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(containsString("5556918")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId(id);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference(id);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/1"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoMatchUrl() {
|
||||
String methodName = "testTransactionUpdateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoOperationSpecified() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.getId().setValue("testTransactionWithUpdateXXX01");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithUpdate01");
|
||||
res.add(p1);
|
||||
|
||||
Observation p2 = new Observation();
|
||||
p2.getId().setValue("testTransactionWithUpdateXXX02");
|
||||
p2.getIdentifier().setSystem("system").setValue("testTransactionWithUpdate02");
|
||||
p2.setSubject(new ResourceReferenceDt("Patient/testTransactionWithUpdateXXX01"));
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertFalse(p1.getId().isEmpty());
|
||||
assertFalse(p2.getId().isEmpty());
|
||||
assertEquals("testTransactionWithUpdateXXX01", p1.getId().getIdPart());
|
||||
assertEquals("testTransactionWithUpdateXXX02", p2.getId().getIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX01", p1.getId().getVersionIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX02", p2.getId().getVersionIdPart());
|
||||
assertEquals(p1.getId().toUnqualified().toVersionless(), p2.getSubject().getReference());
|
||||
|
||||
IdDt p1id = p1.getId().toUnqualified().toVersionless();
|
||||
IdDt p1idWithVer = p1.getId().toUnqualified();
|
||||
IdDt p2id = p2.getId().toUnqualified().toVersionless();
|
||||
IdDt p2idWithVer = p2.getId().toUnqualified();
|
||||
|
||||
/*
|
||||
* Make some changes
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
p1 = new Patient();
|
||||
p1.getId().setValue("testTransactionWithUpdateXXX01");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithUpdate01");
|
||||
p1.addName().addFamily("Name1");
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Observation();
|
||||
p2.getId().setValue("testTransactionWithUpdateXXX02");
|
||||
p2.getIdentifier().setSystem("system").setValue("testTransactionWithUpdate02");
|
||||
p2.setSubject(new ResourceReferenceDt("Patient/testTransactionWithUpdateXXX01"));
|
||||
p2.addReferenceRange().setHigh(new QuantityDt(123L));
|
||||
res.add(p2);
|
||||
|
||||
List<IResource> results = ourSystemDao.transaction(res);
|
||||
|
||||
assertEquals(p1id, results.get(1).getId().toUnqualified().toVersionless());
|
||||
assertEquals(p2id, results.get(2).getId().toUnqualified().toVersionless());
|
||||
assertNotEquals(p1idWithVer, results.get(1).getId().toUnqualified());
|
||||
assertNotEquals(p2idWithVer, results.get(2).getId().toUnqualified());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDelete() throws Exception {
|
||||
|
||||
/*
|
||||
* Create 3
|
||||
*/
|
||||
|
||||
List<IResource> res;
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p2);
|
||||
|
||||
Patient p3 = new Patient();
|
||||
p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p3);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(3, results.size());
|
||||
|
||||
/*
|
||||
* Now delete 2
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
List<IResource> existing = results.getResources(0, 3);
|
||||
|
||||
p1 = new Patient();
|
||||
p1.setId(existing.get(0).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Patient();
|
||||
p2.setId(existing.get(1).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(1, results2.size());
|
||||
List<IResource> existing2 = results2.getResources(0, 1);
|
||||
assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
|
||||
ourLocationDao = ourCtx.getBean("myLocationDaoDstu1", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu1", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -9,6 +9,7 @@ import org.springframework.web.context.WebApplicationContext;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
|
@ -48,7 +49,7 @@ public class JpaServerDemo extends RestfulServer {
|
|||
* The system provider implements non-resource-type methods, such as
|
||||
* transaction, and global history.
|
||||
*/
|
||||
JpaSystemProviderDstu1 systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu1.class);
|
||||
JpaSystemProviderDstu2 systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
|
||||
setPlainProviders(systemProvider);
|
||||
|
||||
/*
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue