History operation working
This commit is contained in:
parent
84096da74d
commit
2e5aac29d1
|
@ -1,5 +1,10 @@
|
|||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
|
@ -8,15 +13,17 @@ import ca.uhn.fhir.util.ElementUtil;
|
|||
|
||||
public abstract class BaseResource extends BaseElement implements IResource {
|
||||
|
||||
@Child(name = "contained", order = 2, min = 0, max = 1)
|
||||
private ContainedDt myContained;
|
||||
|
||||
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
||||
private CodeDt myLanguage;
|
||||
|
||||
private Map<ResourceMetadataKeyEnum, Object> myResourceMetadata;
|
||||
|
||||
@Child(name = "text", order = 1, min = 0, max = 1)
|
||||
private NarrativeDt myText;
|
||||
|
||||
@Child(name="contained", order=2, min=0, max=1)
|
||||
private ContainedDt myContained;
|
||||
|
||||
@Override
|
||||
public ContainedDt getContained() {
|
||||
if (myContained == null) {
|
||||
|
@ -25,14 +32,19 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||
return myContained;
|
||||
}
|
||||
|
||||
public void setContained(ContainedDt theContained) {
|
||||
myContained = theContained;
|
||||
}
|
||||
|
||||
public CodeDt getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ResourceMetadataKeyEnum, Object> getResourceMetadata() {
|
||||
if (myResourceMetadata == null) {
|
||||
myResourceMetadata = new HashMap<ResourceMetadataKeyEnum, Object>();
|
||||
}
|
||||
return myResourceMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarrativeDt getText() {
|
||||
if (myText == null) {
|
||||
myText = new NarrativeDt();
|
||||
|
@ -40,22 +52,32 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||
return myText;
|
||||
}
|
||||
|
||||
public void setContained(ContainedDt theContained) {
|
||||
myContained = theContained;
|
||||
}
|
||||
|
||||
public void setLanguage(CodeDt theLanguage) {
|
||||
myLanguage = theLanguage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceMetadata(Map<ResourceMetadataKeyEnum, Object> theMap) {
|
||||
Validate.notNull(theMap, "The Map must not be null");
|
||||
myResourceMetadata = theMap;
|
||||
}
|
||||
|
||||
public void setText(NarrativeDt theText) {
|
||||
myText = theText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code>
|
||||
* if all content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
|
||||
* Intended to be called by extending classes {@link #isEmpty()}
|
||||
* implementations, returns <code>true</code> if all content in this
|
||||
* superclass instance is empty per the semantics of {@link #isEmpty()}.
|
||||
*/
|
||||
@Override
|
||||
protected boolean isBaseEmpty() {
|
||||
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package ca.uhn.fhir.model.api;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
|
@ -15,7 +17,6 @@ public class BundleEntry extends BaseBundle {
|
|||
* NB: add any new fields to the isEmpty() method!!!
|
||||
*****************************************************/
|
||||
//@formatter:on
|
||||
private StringDt myEntryId;
|
||||
private StringDt myLinkSelf;
|
||||
private InstantDt myPublished;
|
||||
private IResource myResource;
|
||||
|
@ -28,18 +29,11 @@ public class BundleEntry extends BaseBundle {
|
|||
public boolean isEmpty() {
|
||||
//@formatter:off
|
||||
return super.isEmpty() &&
|
||||
ElementUtil.isEmpty(myEntryId, myLinkSelf, myPublished, myResource, myTitle, myUpdated, mySummary) &&
|
||||
ElementUtil.isEmpty(myLinkSelf, myPublished, myResource, myTitle, myUpdated, mySummary) &&
|
||||
ElementUtil.isEmpty(myCategories);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
public StringDt getEntryId() {
|
||||
if (myEntryId == null) {
|
||||
myEntryId = new StringDt();
|
||||
}
|
||||
return myEntryId;
|
||||
}
|
||||
|
||||
public StringDt getLinkSelf() {
|
||||
if (myLinkSelf == null) {
|
||||
myLinkSelf = new StringDt();
|
||||
|
@ -103,4 +97,14 @@ public class BundleEntry extends BaseBundle {
|
|||
return myCategories;
|
||||
}
|
||||
|
||||
public void setPublished(InstantDt thePublished) {
|
||||
Validate.notNull(thePublished, "Published may not be null");
|
||||
myPublished = thePublished;
|
||||
}
|
||||
|
||||
public void setUpdated(InstantDt theUpdated) {
|
||||
Validate.notNull(theUpdated, "Updated may not be null");
|
||||
myUpdated = theUpdated;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
|
||||
|
@ -20,4 +22,20 @@ public interface IResource extends ICompositeElement {
|
|||
|
||||
NarrativeDt getText();
|
||||
|
||||
/**
|
||||
* Returns the metadata map for this object, creating it if neccesary. Metadata
|
||||
* entries are used to get/set feed bundle entries, such as the
|
||||
* resource version, or the last updated timestamp.
|
||||
*/
|
||||
Map<ResourceMetadataKeyEnum, Object> getResourceMetadata();
|
||||
|
||||
/**
|
||||
* Sets the metadata map for this object. Metadata
|
||||
* entries are used to get/set feed bundle entries, such as the
|
||||
* resource version, or the last updated timestamp.
|
||||
*
|
||||
* @throws NullPointerException The map must not be null
|
||||
*/
|
||||
void setResourceMetadata(Map<ResourceMetadataKeyEnum, Object> theMap);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
||||
public enum ResourceMetadataKeyEnum {
|
||||
|
||||
VERSION_ID,
|
||||
|
||||
/**
|
||||
* The value for this key is the bundle entry <b>Published</b> time. This
|
||||
* is defined by FHIR as "Time resource copied into the feed", which is generally
|
||||
* best left to the current time.
|
||||
* <p>
|
||||
* Values for this key are of type {@link InstantDt}
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Server Note</b>: In servers, it is generally advisable to leave this
|
||||
* value <code>null</code>, in which case the server will substitute the
|
||||
* current time automatically.
|
||||
* </p>
|
||||
*
|
||||
* @see InstantDt
|
||||
*/
|
||||
PUBLISHED,
|
||||
|
||||
/**
|
||||
* The value for this key is the bundle entry <b>Updated</b> time. This
|
||||
* is defined by FHIR as "Last Updated for resource".
|
||||
* <p>
|
||||
* Values for this key are of type {@link InstantDt}
|
||||
* </p>
|
||||
*
|
||||
* @see InstantDt
|
||||
*/
|
||||
UPDATED;
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.model.dstu.resource;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.BaseElement;
|
||||
import ca.uhn.fhir.model.api.BaseResource;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
|
@ -10,7 +11,7 @@ import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
|
||||
@ResourceDef(name="Binary", profile="http://hl7.org/fhir/profiles/Binary", id="binary")
|
||||
public class Binary extends BaseElement implements IResource {
|
||||
public class Binary extends BaseResource implements IResource {
|
||||
|
||||
// TODO: implement binary
|
||||
|
||||
|
|
|
@ -90,12 +90,11 @@ public abstract class BaseParser implements IParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the
|
||||
* encoded values.
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives
|
||||
* will not be included in the encoded values.
|
||||
*/
|
||||
public boolean getSuppressNarratives() {
|
||||
return mySuppressNarratives;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
eventWriter.writeStartObject();
|
||||
|
||||
writeTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getEntryId());
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
|
||||
|
||||
eventWriter.writeStartArray("link");
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
|
@ -818,6 +818,14 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IdDt theIdDt) {
|
||||
if (StringUtils.isNotBlank(theIdDt.getValue())) {
|
||||
theEventWriter.write(theElementName, theIdDt.getValue());
|
||||
} else {
|
||||
theEventWriter.writeNull(theElementName);
|
||||
}
|
||||
}
|
||||
|
||||
private class HeldExtension {
|
||||
|
||||
private ExtensionDt myUndeclaredExtension;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -36,10 +36,12 @@ 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.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
class ParserState<T extends IElement> {
|
||||
|
||||
|
@ -196,15 +198,54 @@ class ParserState<T extends IElement> {
|
|||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
populateResourceMetadata();
|
||||
pop();
|
||||
}
|
||||
|
||||
private void populateResourceMetadata() {
|
||||
if (myEntry.getResource() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<ResourceMetadataKeyEnum, Object> metadata = myEntry.getResource().getResourceMetadata();
|
||||
if (myEntry.getPublished().isEmpty() == false) {
|
||||
metadata.put(ResourceMetadataKeyEnum.PUBLISHED, myEntry.getPublished());
|
||||
}
|
||||
if (myEntry.getUpdated().isEmpty() == false) {
|
||||
metadata.put(ResourceMetadataKeyEnum.UPDATED, myEntry.getUpdated());
|
||||
}
|
||||
if (!myEntry.getLinkSelf().isEmpty()) {
|
||||
String subStr = "/" + Constants.PARAM_HISTORY + "/";
|
||||
String linkSelfValue = myEntry.getLinkSelf().getValue();
|
||||
int startIndex = linkSelfValue.indexOf(subStr);
|
||||
if (startIndex > 0) {
|
||||
startIndex = startIndex + subStr.length();
|
||||
int endIndex = linkSelfValue.indexOf('?', startIndex);
|
||||
if (endIndex == -1) {
|
||||
endIndex = linkSelfValue.length();
|
||||
}
|
||||
String versionId = linkSelfValue.substring(startIndex, endIndex);
|
||||
if (isNotBlank(versionId)) {
|
||||
int idx = versionId.indexOf('/');
|
||||
if (idx != -1) {
|
||||
// Just in case
|
||||
ourLog.warn("Bundle entry link-self contains path information beyond version (this will be ignored): {}", versionId);
|
||||
versionId = versionId.substring(0, idx);
|
||||
}
|
||||
metadata.put(ResourceMetadataKeyEnum.VERSION_ID, versionId);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("title".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getTitle()));
|
||||
} else if ("id".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getEntryId()));
|
||||
push(new AtomPrimitiveState(myEntry.getId()));
|
||||
} else if ("link".equals(theLocalPart)) {
|
||||
push(new AtomLinkState(myEntry));
|
||||
} else if ("updated".equals(theLocalPart)) {
|
||||
|
@ -550,8 +591,7 @@ class ParserState<T extends IElement> {
|
|||
|
||||
}
|
||||
|
||||
private class SwallowChildrenWholeState extends BaseState
|
||||
{
|
||||
private class SwallowChildrenWholeState extends BaseState {
|
||||
|
||||
private int myDepth;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
|||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
|
@ -122,7 +123,9 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
eventWriter.writeStartElement("entry");
|
||||
|
||||
writeTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getEntryId());
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
|
||||
|
||||
if (!nextEntry.getLinkSelf().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
|
@ -609,4 +612,12 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(XMLStreamWriter theEventWriter, String theElementName, IdDt theIdDt) throws XMLStreamException {
|
||||
theEventWriter.writeStartElement(theElementName);
|
||||
if (StringUtils.isNotBlank(theIdDt.getValue())) {
|
||||
theEventWriter.writeCharacters(theIdDt.getValue());
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,12 @@ public class GetClientInvocation extends BaseClientInvocation {
|
|||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public GetClientInvocation(String theUrlPath) {
|
||||
myParameters = Collections.emptyMap();
|
||||
myUrlPath = theUrlPath;
|
||||
}
|
||||
|
||||
|
||||
public GetClientInvocation(String... theUrlFragments) {
|
||||
myParameters = Collections.emptyMap();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
|
|
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
|||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
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;
|
||||
|
@ -84,8 +85,9 @@ public abstract class BaseMethodBinding {
|
|||
Create create = theMethod.getAnnotation(Create.class);
|
||||
Update update = theMethod.getAnnotation(Update.class);
|
||||
Delete delete = theMethod.getAnnotation(Delete.class);
|
||||
History history = theMethod.getAnnotation(History.class);
|
||||
// ** if you add another annotation above, also add it to the next line:
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update,delete)) {
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update,delete,history)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -115,6 +117,8 @@ public abstract class BaseMethodBinding {
|
|||
return new UpdateMethodBinding(theMethod, theContext);
|
||||
} else if (delete != null) {
|
||||
return new DeleteMethodBinding(theMethod, theContext, theProvider);
|
||||
} else if (history != null) {
|
||||
return new HistoryMethodBinding(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -22,8 +25,12 @@ 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.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
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.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
@ -38,7 +45,15 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|||
public abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||
|
||||
protected static final Set<String> ALLOWED_PARAMS;
|
||||
static {
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
set.add(Constants.PARAM_FORMAT);
|
||||
set.add(Constants.PARAM_NARRATIVE);
|
||||
set.add(Constants.PARAM_PRETTY);
|
||||
ALLOWED_PARAMS = Collections.unmodifiableSet(set);
|
||||
}
|
||||
private MethodReturnTypeEnum myMethodReturnType;
|
||||
|
||||
private String myResourceName;
|
||||
|
||||
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt) {
|
||||
|
@ -55,12 +70,14 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
||||
if (theReturnResourceType != null) {
|
||||
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
||||
if (resourceDefAnnotation == null) {
|
||||
throw new ConfigurationException(theReturnResourceType.getCanonicalName() + " has no @" + ResourceDef.class.getSimpleName() + " annotation");
|
||||
}
|
||||
myResourceName = resourceDefAnnotation.name();
|
||||
}
|
||||
}
|
||||
|
||||
public MethodReturnTypeEnum getMethodReturnType() {
|
||||
return myMethodReturnType;
|
||||
|
@ -113,7 +130,6 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
throw new IllegalStateException("Should not get here!");
|
||||
}
|
||||
|
||||
|
||||
public abstract List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
|
@ -165,13 +181,40 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
}
|
||||
|
||||
private IdDt getIdFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
||||
Object retValObj = theResourceMetadata.get(theKey);
|
||||
if (retValObj == null) {
|
||||
return null;
|
||||
} else if (retValObj instanceof String) {
|
||||
if (isNotBlank((String) retValObj)) {
|
||||
return new IdDt((String) retValObj);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (retValObj instanceof IdDt) {
|
||||
if (((IdDt) retValObj).isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return (IdDt) retValObj;
|
||||
}
|
||||
}
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + IdDt.class.getCanonicalName());
|
||||
}
|
||||
|
||||
static {
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
set.add(Constants.PARAM_FORMAT);
|
||||
set.add(Constants.PARAM_NARRATIVE);
|
||||
set.add(Constants.PARAM_PRETTY);
|
||||
ALLOWED_PARAMS = Collections.unmodifiableSet(set);
|
||||
private InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
||||
Object retValObj = theResourceMetadata.get(theKey);
|
||||
if (retValObj == null) {
|
||||
return null;
|
||||
} else if (retValObj instanceof Date) {
|
||||
return new InstantDt((Date) retValObj);
|
||||
} else if (retValObj instanceof InstantDt) {
|
||||
if (((InstantDt) retValObj).isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return (InstantDt) retValObj;
|
||||
}
|
||||
}
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + InstantDt.class.getCanonicalName());
|
||||
}
|
||||
|
||||
private IParser getNewParser(EncodingUtil theResponseEncoding, boolean thePrettyPrint, NarrativeModeEnum theNarrativeMode) {
|
||||
|
@ -222,7 +265,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
RuntimeResourceDefinition def = getContext().getResourceDefinition(next);
|
||||
|
||||
if (next.getId() != null && StringUtils.isNotBlank(next.getId().getValue())) {
|
||||
entry.getEntryId().setValue(next.getId().getValue());
|
||||
entry.getId().setValue(next.getId().getValue());
|
||||
entry.getTitle().setValue(def.getName() + " " + next.getId().getValue());
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
@ -230,7 +273,37 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
b.append('/');
|
||||
b.append(def.getName());
|
||||
b.append('/');
|
||||
b.append(next.getId().getValue());
|
||||
String resId = next.getId().getValue();
|
||||
b.append(resId);
|
||||
|
||||
/*
|
||||
* If this is a history operation, we add the version of the
|
||||
* resource to the self link to indicate the version
|
||||
*/
|
||||
if (getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_INSTANCE || getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_TYPE || getSystemOperationType() == RestfulOperationSystemEnum.HISTORY_SYSTEM) {
|
||||
IdDt versionId = getIdFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.VERSION_ID);
|
||||
if (versionId != null) {
|
||||
b.append('/');
|
||||
b.append(Constants.PARAM_HISTORY);
|
||||
b.append('/');
|
||||
b.append(versionId.getValue());
|
||||
} else {
|
||||
throw new InternalErrorException("Server did not provide a VERSION_ID in the resource metadata for resource with ID " + resId);
|
||||
}
|
||||
}
|
||||
|
||||
InstantDt published = getInstantFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.PUBLISHED);
|
||||
if (published == null) {
|
||||
entry.getPublished().setToCurrentTimeInLocalTimeZone();
|
||||
} else {
|
||||
entry.setPublished(published);
|
||||
}
|
||||
|
||||
InstantDt updated = getInstantFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.UPDATED);
|
||||
if (updated != null) {
|
||||
entry.setUpdated(updated);
|
||||
}
|
||||
|
||||
boolean haveQ = false;
|
||||
if (thePrettyPrint) {
|
||||
b.append('?').append(Constants.PARAM_PRETTY).append("=true");
|
||||
|
@ -269,7 +342,6 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
|
|
@ -1,43 +1,42 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
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.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.GetClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class HistoryMethodBinding extends BaseMethodBinding {
|
||||
public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
||||
|
||||
private final Integer myIdParamIndex;
|
||||
private final RestfulOperationTypeEnum myResourceOperationType;
|
||||
private final Class<? extends IResource> myType;
|
||||
private final RestfulOperationSystemEnum mySystemOperationType;
|
||||
private String myResourceName;
|
||||
private Integer mySinceParamIndex;
|
||||
private Integer myCountParamIndex;
|
||||
|
||||
public HistoryMethodBinding(Method theMethod, FhirContext theConetxt, IResourceProvider theProvider) {
|
||||
super(theMethod, theConetxt);
|
||||
super(toReturnType(theMethod, theProvider), theMethod, theConetxt);
|
||||
|
||||
myIdParamIndex = Util.findIdParameterIndex(theMethod);
|
||||
mySinceParamIndex = Util.findSinceParameterIndex(theMethod);
|
||||
|
@ -69,14 +68,24 @@ public class HistoryMethodBinding extends BaseMethodBinding {
|
|||
|
||||
if (type != History.AllResources.class) {
|
||||
myResourceName = theConetxt.getResourceDefinition(type).getName();
|
||||
myType = type;
|
||||
} else {
|
||||
myResourceName = null;
|
||||
myType = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Class<? extends IResource> toReturnType(Method theMethod, IResourceProvider theProvider) {
|
||||
if (theProvider != null) {
|
||||
return theProvider.getResourceType();
|
||||
}
|
||||
History historyAnnotation = theMethod.getAnnotation(History.class);
|
||||
Class<? extends IResource> type = historyAnnotation.resourceType();
|
||||
if (type != History.AllResources.class) {
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return myResourceOperationType;
|
||||
|
@ -89,21 +98,63 @@ public class HistoryMethodBinding extends BaseMethodBinding {
|
|||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (myResourceName!=null) {
|
||||
b.append(myResourceName);
|
||||
if (myIdParamIndex!=null) {
|
||||
IdDt id = (IdDt)theArgs[myIdParamIndex];
|
||||
if (id==null||isBlank(id.getValue())) {
|
||||
throw new NullPointerException("ID can not be null");
|
||||
}
|
||||
b.append('/');
|
||||
b.append(id.getValue());
|
||||
}
|
||||
}
|
||||
if (b.length()>0) {
|
||||
b.append('/');
|
||||
}
|
||||
b.append(Constants.PARAM_HISTORY);
|
||||
|
||||
return new GetClientInvocation(b.toString());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation") // ObjectUtils.equals is replaced by a JDK7 method..
|
||||
@Override
|
||||
public boolean matches(Request theRequest) {
|
||||
if (!Constants.PARAM_HISTORY.equals(theRequest.getOperation())) {
|
||||
return false;
|
||||
}
|
||||
if (theRequest.getResourceName() == null) {
|
||||
return mySystemOperationType == RestfulOperationSystemEnum.HISTORY_SYSTEM;
|
||||
}
|
||||
if (!ObjectUtils.equals(theRequest.getResourceName(),myResourceName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean haveIdParam= theRequest.getId() != null && !theRequest.getId().isEmpty();
|
||||
boolean wantIdParam = myIdParamIndex != null;
|
||||
if (haveIdParam!=wantIdParam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (theRequest.getVersion() != null && !theRequest.getVersion().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public ReturnTypeEnum getReturnType() {
|
||||
return ReturnTypeEnum.BUNDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
public List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] args = new Object[getMethod().getParameterTypes().length];
|
||||
if (myCountParamIndex != null) {
|
||||
String[] countValues = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||
String[] countValues = theParameterValues.remove(Constants.PARAM_COUNT);
|
||||
if (countValues.length > 0 && StringUtils.isNotBlank(countValues[0])) {
|
||||
try {
|
||||
args[myCountParamIndex] = new IntegerDt(countValues[0]);
|
||||
|
@ -113,7 +164,7 @@ public class HistoryMethodBinding extends BaseMethodBinding {
|
|||
}
|
||||
}
|
||||
if (mySinceParamIndex != null) {
|
||||
String[] sinceValues = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||
String[] sinceValues = theParameterValues.remove(Constants.PARAM_SINCE);
|
||||
if (sinceValues.length > 0 && StringUtils.isNotBlank(sinceValues[0])) {
|
||||
try {
|
||||
args[mySinceParamIndex] = new InstantDt(sinceValues[0]);
|
||||
|
@ -122,21 +173,23 @@ public class HistoryMethodBinding extends BaseMethodBinding {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myIdParamIndex!=null) {
|
||||
args[myIdParamIndex] = theId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Request theRequest) {
|
||||
if (!theRequest.getOperation().equals(Constants.PARAM_HISTORY)) {
|
||||
return false;
|
||||
}
|
||||
if (theRequest.getResourceName() == null) {
|
||||
return mySystemOperationType == RestfulOperationSystemEnum.HISTORY_SYSTEM;
|
||||
}
|
||||
if (!theRequest.getResourceName().equals(myResourceName)) {
|
||||
return false;
|
||||
Object response;
|
||||
try {
|
||||
response = getMethod().invoke(theResourceProvider, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
return toResourceList(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,10 +48,10 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
private Map<Class<? extends IResource>, IResourceProvider> myTypeToProvider = new HashMap<Class<? extends IResource>, IResourceProvider>();
|
||||
private boolean myUseBrowserFriendlyContentTypes;
|
||||
private ISecurityManager securityManager;
|
||||
|
||||
private BaseMethodBinding myServerConformanceMethod;
|
||||
|
||||
public RestfulServer() {
|
||||
myFhirContext = new FhirContext();
|
||||
myServerConformanceProvider=new ServerConformanceProvider(this);
|
||||
}
|
||||
|
||||
|
@ -260,13 +260,17 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (nextString.startsWith(Constants.PARAM_HISTORY)) {
|
||||
if (nextString.startsWith("_")) {
|
||||
if (operation !=null) {
|
||||
throw new InvalidRequestException("URL Path contains two operations (part beginning with _): " + requestPath);
|
||||
}
|
||||
operation = nextString;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
versionId = new IdDt(tok.nextToken());
|
||||
} else {
|
||||
throw new InvalidRequestException("_history search specified but no version requested in URL");
|
||||
}
|
||||
}
|
||||
String nextString = tok.nextToken();
|
||||
versionId = new IdDt(nextString);
|
||||
}
|
||||
|
||||
// TODO: look for more tokens for version, compartments, etc...
|
||||
|
@ -347,7 +351,6 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
|
||||
ourLog.info("Got {} resource providers", myTypeToProvider.size());
|
||||
|
||||
myFhirContext = new FhirContext(myTypeToProvider.keySet());
|
||||
myFhirContext.setNarrativeGenerator(myNarrativeGenerator);
|
||||
|
||||
for (IResourceProvider provider : myTypeToProvider.values()) {
|
||||
|
|
|
@ -7,8 +7,10 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
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.PathSpecification;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
|
@ -22,6 +24,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
|
@ -82,6 +85,24 @@ public void deletePatient(@IdParam IdDt theId) {
|
|||
//END SNIPPET: delete
|
||||
|
||||
|
||||
//START SNIPPET: history
|
||||
@History()
|
||||
public List<Patient> getPatientHistory(@IdParam IdDt theId) {
|
||||
List<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("Smith");
|
||||
|
||||
// Set the ID and version
|
||||
patient.setId(theId);
|
||||
patient.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, new IdDt("1"));
|
||||
|
||||
// ...populate the rest...
|
||||
return retVal;
|
||||
}
|
||||
//END SNIPPET: history
|
||||
|
||||
|
||||
//START SNIPPET: vread
|
||||
@Read()
|
||||
public Patient getResourceById(@IdParam IdDt theId,
|
||||
|
@ -310,8 +331,7 @@ return retVal;
|
|||
|
||||
|
||||
public static void main(String[] args) throws DataFormatException, IOException {
|
||||
|
||||
|
||||
//nothing
|
||||
}
|
||||
|
||||
|
||||
|
@ -348,6 +368,24 @@ public interface MetadataClient extends IRestfulClient {
|
|||
}
|
||||
//END SNIPPET: metadataClient
|
||||
|
||||
public interface HistoryClient {
|
||||
//START SNIPPET: historyClient
|
||||
// Server level (history of ALL resources)
|
||||
@History
|
||||
Bundle getHistoryServer();
|
||||
|
||||
// Type level (history of all resources of a given type)
|
||||
@History(resourceType=Patient.class)
|
||||
Bundle getHistoryPatientType();
|
||||
|
||||
// Instance level (history of a specific resource instance by type and ID)
|
||||
@History(resourceType=Patient.class)
|
||||
Bundle getHistoryPatientInstance(@IdParam IdDt theId);
|
||||
//END SNIPPET: historyClient
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void bbbbb() throws DataFormatException, IOException {
|
||||
//START SNIPPET: metadataClientUsage
|
||||
FhirContext ctx = new FhirContext();
|
||||
|
@ -358,6 +396,9 @@ System.out.println(ctx.newXmlParser().encodeResourceToString(metadata));
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#instance_history">Instance - History</a>
|
||||
<a href="#history">Instance - History</a>
|
||||
</td>
|
||||
<td>
|
||||
Retrieve the update history for a particular resource
|
||||
|
@ -89,7 +89,7 @@
|
|||
<td>
|
||||
<a href="#instance_update">Type - Search</a>
|
||||
<macro name="toc">
|
||||
<param name="section" value="8"/>
|
||||
<param name="section" value="7"/>
|
||||
<param name="fromDepth" value="2"/>
|
||||
</macro>
|
||||
</td>
|
||||
|
@ -107,7 +107,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#type_history">Type - History</a>
|
||||
<a href="#history">Type - History</a>
|
||||
</td>
|
||||
<td>
|
||||
Retrieve the update history for a particular resource type
|
||||
|
@ -115,7 +115,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#type_history">Type - Validate</a>
|
||||
<a href="#type_validate">Type - Validate</a>
|
||||
</td>
|
||||
<td>
|
||||
Check that the content would be acceptable as an update
|
||||
|
@ -139,7 +139,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#system_history">System - History</a>
|
||||
<a href="#history">System - History</a>
|
||||
</td>
|
||||
<td>
|
||||
Retrieve the update history for all resources
|
||||
|
@ -157,6 +157,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<a name="instance_read"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -164,7 +165,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Instance Level - Read">
|
||||
<a name="instance_read"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -186,6 +186,7 @@
|
|||
<code>http://fhir.example.com/Patient/111</code>
|
||||
</p>
|
||||
|
||||
<a name="instance_vread"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -193,7 +194,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Instance Level - VRead">
|
||||
<a name="instance_vread"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -215,6 +215,7 @@
|
|||
<code>http://fhir.example.com/Patient/111/_history/2</code>
|
||||
</p>
|
||||
|
||||
<a name="instance_update"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -222,7 +223,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Instance Level - Update">
|
||||
<a name="instance_update"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -283,6 +283,7 @@
|
|||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="instance_delete"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -290,7 +291,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Instance Level - Delete">
|
||||
<a name="instance_delete"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -329,19 +329,7 @@
|
|||
<code>http://fhir.example.com/Patient/111</code>
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Instance Level - History">
|
||||
<a name="instance_history"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="type_create"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -349,7 +337,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Type Level - Create">
|
||||
<a name="type_create"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -394,6 +381,7 @@
|
|||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="type_search"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -401,7 +389,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Type Level - Search">
|
||||
<a name="type_search"/>
|
||||
|
||||
<p>
|
||||
The
|
||||
|
@ -698,19 +685,7 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Type Level - History">
|
||||
<a name="type_history"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="type_validate"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -718,12 +693,12 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="Type Level - Validate">
|
||||
<a name="type_validate"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="system_conformance"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -731,7 +706,6 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="System Level - Conformance">
|
||||
<a name="system_conformance"/>
|
||||
|
||||
<p>
|
||||
FHIR defines that a FHIR Server must be able to export a conformance statement,
|
||||
|
@ -779,6 +753,7 @@
|
|||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="system_transaction"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -786,25 +761,12 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="System Level - Transaction">
|
||||
<a name="system_transaction"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="System Level - History">
|
||||
<a name="system_history"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="system_search"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
|
@ -812,14 +774,71 @@
|
|||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="System Level - Search">
|
||||
<a name="system_search"/>
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="history"/>
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
<!-- ****************************************************************** -->
|
||||
|
||||
<section name="History (Instance, Type, Server)">
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#history"><b>history</b></a>
|
||||
operation retrieves a historical collection of all versions of a single resource
|
||||
<i>(instance history)</i>, all resources of a given type <i>(type history)</i>,
|
||||
or all resources of any type on a server <i>(server history)</i>.
|
||||
</p>
|
||||
<p>
|
||||
History methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/History.html">@History</a>
|
||||
annotation, and will have additional requirements depending on the kind
|
||||
of history method intended:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
For an <b>Instance History</b> method, the method must have a parameter
|
||||
annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/IdParam.html">@IdParam</a>
|
||||
annotation, indicating the ID of the resource for which to return history.
|
||||
</li>
|
||||
<li>
|
||||
For an <b>Type History</b> method, the method must not have any @IdParam parameter.
|
||||
</li>
|
||||
<li>
|
||||
For an <b>Server History</b> method, the method must not have any @IdParam parameter
|
||||
and must not be found in a ResourceProvider definition.
|
||||
<!-- TODO: make ResourceProvider a link to a defintion of these on the RESTFul server page -->
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
The following snippet shows how to define a history method on a server:
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="history" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
The following snippet shows how to define various history methods in a client.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="historyClient" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.context;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.BaseResource;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IExtension;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -17,7 +18,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
||||
@ResourceDef(name = "ResourceWithExtensionsA", id="0001")
|
||||
public class ResourceWithExtensionsA implements IResource {
|
||||
public class ResourceWithExtensionsA extends BaseResource {
|
||||
|
||||
/*
|
||||
* NB: several unit tests depend on the structure here
|
||||
|
|
|
@ -224,7 +224,7 @@ public class JsonParserTest {
|
|||
assertEquals("urn:uuid:0b754ff9-03cf-4322-a119-15019af8a3", bundle.getBundleId().getValue());
|
||||
|
||||
BundleEntry entry = bundle.getEntries().get(0);
|
||||
assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/101", entry.getEntryId().getValue());
|
||||
assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/101", entry.getId().getValue());
|
||||
assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/101/_history/1", entry.getLinkSelf().getValue());
|
||||
assertEquals("2014-03-10T11:55:59Z", entry.getUpdated().getValueAsString());
|
||||
|
||||
|
|
|
@ -440,7 +440,7 @@ public class XmlParserTest {
|
|||
|
||||
BundleEntry entry = bundle.getEntries().get(0);
|
||||
assertEquals("HL7, Inc (FHIR Project)", entry.getAuthorName().getValue());
|
||||
assertEquals("http://hl7.org/fhir/valueset/256a5231-a2bb-49bd-9fea-f349d428b70d", entry.getEntryId().getValue());
|
||||
assertEquals("http://hl7.org/fhir/valueset/256a5231-a2bb-49bd-9fea-f349d428b70d", entry.getId().getValue());
|
||||
|
||||
ValueSet resource = (ValueSet) entry.getResource();
|
||||
assertEquals("LOINC Codes for Cholesterol", resource.getName().getValue());
|
||||
|
|
|
@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
|
|||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -29,7 +30,9 @@ import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
|
@ -37,6 +40,7 @@ import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
|||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||
|
@ -64,6 +68,168 @@ public class ClientTest {
|
|||
httpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceInstance() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientInstance(new IdDt("111"));
|
||||
|
||||
assertEquals("http://foo/Patient/111/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceType() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientType();
|
||||
|
||||
assertEquals("http://foo/Patient/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryServer() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryServer();
|
||||
|
||||
assertEquals("http://foo/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
|
@ -28,26 +29,8 @@ import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
|||
|
||||
public interface ITestClient extends IBasicClient {
|
||||
|
||||
@Read(type=Patient.class)
|
||||
Patient getPatientById(@IdParam IdDt theId);
|
||||
|
||||
@Delete(resourceType=Patient.class)
|
||||
MethodOutcome deletePatient(@IdParam IdDt theId);
|
||||
|
||||
@Delete(resourceType=DiagnosticReport.class)
|
||||
void deleteDiagnosticReport(@IdParam IdDt theId);
|
||||
|
||||
@Read(type=Patient.class)
|
||||
Patient getPatientByVersionId(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId);
|
||||
|
||||
@Search(type=Patient.class)
|
||||
Patient findPatientByMrn(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theId);
|
||||
|
||||
@Search(type=Patient.class)
|
||||
Bundle findPatientByName(@RequiredParam(name = Patient.SP_FAMILY) StringDt theId, @OptionalParam(name=Patient.SP_GIVEN) StringDt theGiven);
|
||||
|
||||
@Search()
|
||||
public List<Patient> getPatientMultipleIdentifiers(@RequiredParam(name = "ids") CodingListParam theIdentifiers);
|
||||
@Create
|
||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient);
|
||||
|
||||
@Search()
|
||||
public List<Patient> getPatientByDateRange(@RequiredParam(name = "dateRange") DateRangeParam theIdentifiers);
|
||||
|
@ -56,7 +39,7 @@ public interface ITestClient extends IBasicClient {
|
|||
public List<Patient> getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);
|
||||
|
||||
@Search()
|
||||
public Patient getPatientWithIncludes(@RequiredParam(name = "withIncludes") StringDt theString, @IncludeParam List<PathSpecification> theIncludes);
|
||||
public List<Patient> getPatientMultipleIdentifiers(@RequiredParam(name = "ids") CodingListParam theIdentifiers);
|
||||
|
||||
@Search(queryName="someQueryNoParams")
|
||||
public Patient getPatientNoParams();
|
||||
|
@ -64,13 +47,40 @@ public interface ITestClient extends IBasicClient {
|
|||
@Search(queryName="someQueryOneParam")
|
||||
public Patient getPatientOneParam(@RequiredParam(name="param1") StringDt theParam);
|
||||
|
||||
@Create
|
||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient);
|
||||
|
||||
@Update
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient);
|
||||
@Search()
|
||||
public Patient getPatientWithIncludes(@RequiredParam(name = "withIncludes") StringDt theString, @IncludeParam List<PathSpecification> theIncludes);
|
||||
|
||||
@Update
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @VersionIdParam IdDt theVersion, @ResourceParam Patient thePatient);
|
||||
|
||||
@Update
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient);
|
||||
|
||||
@Delete(resourceType=DiagnosticReport.class)
|
||||
void deleteDiagnosticReport(@IdParam IdDt theId);
|
||||
|
||||
@Delete(resourceType=Patient.class)
|
||||
MethodOutcome deletePatient(@IdParam IdDt theId);
|
||||
|
||||
@Search(type=Patient.class)
|
||||
Patient findPatientByMrn(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theId);
|
||||
|
||||
@Search(type=Patient.class)
|
||||
Bundle findPatientByName(@RequiredParam(name = Patient.SP_FAMILY) StringDt theId, @OptionalParam(name=Patient.SP_GIVEN) StringDt theGiven);
|
||||
|
||||
@History(resourceType=Patient.class)
|
||||
Bundle getHistoryPatientInstance(@IdParam IdDt theId);
|
||||
|
||||
@History(resourceType=Patient.class)
|
||||
Bundle getHistoryPatientType();
|
||||
|
||||
@History
|
||||
Bundle getHistoryServer();
|
||||
|
||||
@Read(type=Patient.class)
|
||||
Patient getPatientById(@IdParam IdDt theId);
|
||||
|
||||
@Read(type=Patient.class)
|
||||
Patient getPatientByVersionId(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId);
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -28,6 +29,7 @@ import org.eclipse.jetty.servlet.ServletHandler;
|
|||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hamcrest.core.IsNot;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hamcrest.core.StringEndsWith;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
@ -37,6 +39,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
|
@ -46,11 +49,13 @@ import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
|||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
|
@ -90,7 +95,8 @@ public class ResfulServerMethodTest {
|
|||
DummyDiagnosticReportResourceProvider reportProvider = new DummyDiagnosticReportResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ServletHolder servletHolder = new ServletHolder(new DummyRestfulServer(patientProvider, profProvider,reportProvider));
|
||||
DummyRestfulServer servlet = new DummyRestfulServer(patientProvider, profProvider,reportProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
@ -161,7 +167,7 @@ public class ResfulServerMethodTest {
|
|||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
BundleEntry entry0 = bundle.getEntries().get(0);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkSelf().getValue());
|
||||
assertEquals("1", entry0.getEntryId().getValue());
|
||||
assertEquals("1", entry0.getId().getValue());
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3&_format=json");
|
||||
status = ourClient.execute(httpGet);
|
||||
|
@ -404,6 +410,110 @@ public class ResfulServerMethodTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceType() throws Exception {
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_history");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = bundle.getEntries().get(0);
|
||||
assertEquals("1", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/1/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = bundle.getEntries().get(1);
|
||||
assertEquals("1", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/1/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceInstance() throws Exception {
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/222/_history");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = bundle.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = bundle.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
|
||||
|
@ -765,6 +875,7 @@ public class ResfulServerMethodTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
|
@ -773,16 +884,7 @@ public class ResfulServerMethodTest {
|
|||
public Map<String, Patient> getIdToPatient() {
|
||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier();
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00001");
|
||||
patient.addName();
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
patient.getId().setValue("1");
|
||||
Patient patient = createPatient1();
|
||||
idToPatient.put("1", patient);
|
||||
}
|
||||
{
|
||||
|
@ -801,6 +903,67 @@ public class ResfulServerMethodTest {
|
|||
return idToPatient;
|
||||
}
|
||||
|
||||
private Patient createPatient1() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier();
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00001");
|
||||
patient.addName();
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
patient.getId().setValue("1");
|
||||
return patient;
|
||||
}
|
||||
|
||||
@History
|
||||
public List<Patient> getHistoryResourceType() {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient older = createPatient1();
|
||||
older.getNameFirstRep().getFamilyFirstRep().setValue("OlderFamily");
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "1");
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new Date(10000L));
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt(new Date(20000L)));
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "1");
|
||||
retVal.add(older);
|
||||
|
||||
Patient newer = createPatient1();
|
||||
newer.getNameFirstRep().getFamilyFirstRep().setValue("NewerFamily");
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "2");
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new Date(10000L));
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt(new Date(30000L)));
|
||||
retVal.add(newer);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@History
|
||||
public List<Patient> getHistoryResourceInstance(@IdParam IdDt theId) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient older = createPatient1();
|
||||
older.setId(theId);
|
||||
older.getNameFirstRep().getFamilyFirstRep().setValue("OlderFamily");
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "1");
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new Date(10000L));
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt(new Date(20000L)));
|
||||
older.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "1");
|
||||
retVal.add(older);
|
||||
|
||||
Patient newer = createPatient1();
|
||||
newer.setId(theId);
|
||||
newer.getNameFirstRep().getFamilyFirstRep().setValue("NewerFamily");
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, "2");
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new Date(10000L));
|
||||
newer.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt(new Date(30000L)));
|
||||
retVal.add(newer);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Update()
|
||||
public MethodOutcome updateDiagnosticReportWithVersion(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId, @ResourceParam DiagnosticReport thePatient) {
|
||||
|
|
Loading…
Reference in New Issue