Merge branch 'master' of github.com:jamesagnew/hapi-fhir
This commit is contained in:
commit
e241b31905
|
@ -25,6 +25,7 @@ import java.util.*;
|
||||||
|
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -453,6 +454,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// References
|
||||||
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||||
for (BaseResourceReferenceDt nextRef : allRefs) {
|
for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||||
IdDt nextId = nextRef.getReference();
|
IdDt nextId = nextRef.getReference();
|
||||||
|
@ -468,6 +470,23 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URIs
|
||||||
|
List<UriDt> allUris = terser.getAllPopulatedChildElementsOfType(nextResource, UriDt.class);
|
||||||
|
for (UriDt nextRef : allUris) {
|
||||||
|
if (nextRef instanceof IIdType) {
|
||||||
|
continue; // No substitution on the resource ID itself!
|
||||||
|
}
|
||||||
|
IdDt nextUriString = new IdDt(nextRef.getValueAsString());
|
||||||
|
if (idSubstitutions.containsKey(nextUriString)) {
|
||||||
|
IdDt newId = idSubstitutions.get(nextUriString);
|
||||||
|
ourLog.info(" * Replacing resource ref {} with {}", nextUriString, newId);
|
||||||
|
nextRef.setValue(newId.getValue());
|
||||||
|
} else {
|
||||||
|
ourLog.debug(" * Reference [{}] does not exist in bundle", nextUriString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
||||||
|
|
|
@ -311,7 +311,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date updateTime, Set<IdType> allIds,
|
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date updateTime, Set<IdType> allIds,
|
||||||
Map<IdType, IdType> idSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, Bundle response, IdentityHashMap<BundleEntryComponent, Integer> originalRequestOrder, List<BundleEntryComponent> theEntries) {
|
Map<IdType, IdType> theIdSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, Bundle response, IdentityHashMap<BundleEntryComponent, Integer> originalRequestOrder, List<BundleEntryComponent> theEntries) {
|
||||||
Set<String> deletedResources = new HashSet<String>();
|
Set<String> deletedResources = new HashSet<String>();
|
||||||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
||||||
Map<BundleEntryComponent, ResourceTable> entriesToProcess = new IdentityHashMap<BundleEntryComponent, ResourceTable>();
|
Map<BundleEntryComponent, ResourceTable> entriesToProcess = new IdentityHashMap<BundleEntryComponent, ResourceTable>();
|
||||||
|
@ -379,10 +379,10 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
res.setId((String) null);
|
res.setId((String) null);
|
||||||
DaoMethodOutcome outcome;
|
DaoMethodOutcome outcome;
|
||||||
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
||||||
if (nextResourceId != null) {
|
if (nextResourceId != null) {
|
||||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
||||||
}
|
}
|
||||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||||
if (outcome.getCreated() == false) {
|
if (outcome.getCreated() == false) {
|
||||||
|
@ -412,7 +412,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String matchUrl = parts.getResourceType() + '?' + parts.getParams();
|
String matchUrl = parts.getResourceType() + '?' + parts.getParams();
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(matchUrl, deleteConflicts, theRequestDetails);
|
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(matchUrl, deleteConflicts, theRequestDetails);
|
||||||
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
||||||
for (ResourceTable deleted : allDeleted) {
|
for (ResourceTable deleted : allDeleted) {
|
||||||
|
@ -453,14 +453,14 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
} else {
|
} else {
|
||||||
matchUrl = parts.getResourceType();
|
matchUrl = parts.getResourceType();
|
||||||
}
|
}
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
outcome = resourceDao.update(res, matchUrl, false, theRequestDetails);
|
outcome = resourceDao.update(res, matchUrl, false, theRequestDetails);
|
||||||
if (Boolean.TRUE.equals(outcome.getCreated())) {
|
if (Boolean.TRUE.equals(outcome.getCreated())) {
|
||||||
conditionalRequestUrls.put(matchUrl, res.getClass());
|
conditionalRequestUrls.put(matchUrl, res.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
||||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -496,14 +496,15 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Refererences
|
||||||
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
||||||
for (IBaseReference nextRef : allRefs) {
|
for (IBaseReference nextRef : allRefs) {
|
||||||
IIdType nextId = nextRef.getReferenceElement();
|
IIdType nextId = nextRef.getReferenceElement();
|
||||||
if (!nextId.hasIdPart()) {
|
if (!nextId.hasIdPart()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (idSubstitutions.containsKey(nextId)) {
|
if (theIdSubstitutions.containsKey(nextId)) {
|
||||||
IdType newId = idSubstitutions.get(nextId);
|
IdType newId = theIdSubstitutions.get(nextId);
|
||||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||||
nextRef.setReference(newId.getValue());
|
nextRef.setReference(newId.getValue());
|
||||||
} else if (nextId.getValue().startsWith("urn:")) {
|
} else if (nextId.getValue().startsWith("urn:")) {
|
||||||
|
@ -513,6 +514,22 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URIs
|
||||||
|
List<UriType> allUris = terser.getAllPopulatedChildElementsOfType(nextResource, UriType.class);
|
||||||
|
for (UriType nextRef : allUris) {
|
||||||
|
if (nextRef instanceof IIdType) {
|
||||||
|
continue; // No substitution on the resource ID itself!
|
||||||
|
}
|
||||||
|
IdType nextUriString = new IdType(nextRef.getValueAsString());
|
||||||
|
if (theIdSubstitutions.containsKey(nextUriString)) {
|
||||||
|
IdType newId = theIdSubstitutions.get(nextUriString);
|
||||||
|
ourLog.info(" * Replacing resource ref {} with {}", nextUriString, newId);
|
||||||
|
nextRef.setValue(newId.getValue());
|
||||||
|
} else {
|
||||||
|
ourLog.debug(" * Reference [{}] does not exist in bundle", nextUriString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
|
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
|
||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
||||||
|
@ -546,7 +563,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdType next : allIds) {
|
for (IdType next : allIds) {
|
||||||
IdType replacement = idSubstitutions.get(next);
|
IdType replacement = theIdSubstitutions.get(next);
|
||||||
if (replacement == null) {
|
if (replacement == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -603,6 +620,23 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String performIdSubstitutionsInMatchUrl(Map<IdType, IdType> theIdSubstitutions, String theMatchUrl) {
|
||||||
|
String matchUrl = theMatchUrl;
|
||||||
|
if (isNotBlank(matchUrl)) {
|
||||||
|
for (Entry<IdType, IdType> nextSubstitutionEntry : theIdSubstitutions.entrySet()) {
|
||||||
|
IdType nextTemporaryId = nextSubstitutionEntry.getKey();
|
||||||
|
IdType nextReplacementId = nextSubstitutionEntry.getValue();
|
||||||
|
String nextTemporaryIdPart = nextTemporaryId.getIdPart();
|
||||||
|
String nextReplacementIdPart = nextReplacementId.getValueAsString();
|
||||||
|
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
|
||||||
|
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
|
||||||
|
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchUrl;
|
||||||
|
}
|
||||||
|
|
||||||
private void populateEntryWithOperationOutcome(BaseServerResponseException caughtEx, BundleEntryComponent nextEntry) {
|
private void populateEntryWithOperationOutcome(BaseServerResponseException caughtEx, BundleEntryComponent nextEntry) {
|
||||||
OperationOutcome oo = new OperationOutcome();
|
OperationOutcome oo = new OperationOutcome();
|
||||||
oo.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics(caughtEx.getMessage());
|
oo.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics(caughtEx.getMessage());
|
||||||
|
@ -664,27 +698,6 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
return transaction((ServletRequestDetails) theRequestDetails, theRequest, actionName);
|
return transaction((ServletRequestDetails) theRequestDetails, theRequest, actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private String performIdSubstitutionsInMatchUrl(Map<IdType, IdType> theIdSubstitutions, String theMatchUrl) {
|
|
||||||
String matchUrl = theMatchUrl;
|
|
||||||
if (isNotBlank(matchUrl)) {
|
|
||||||
for (Entry<IdType, IdType> nextSubstitutionEntry : theIdSubstitutions.entrySet()) {
|
|
||||||
IdType nextTemporaryId = nextSubstitutionEntry.getKey();
|
|
||||||
IdType nextReplacementId = nextSubstitutionEntry.getValue();
|
|
||||||
String nextTemporaryIdPart = nextTemporaryId.getIdPart();
|
|
||||||
String nextReplacementIdPart = nextReplacementId.getValueAsString();
|
|
||||||
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
|
|
||||||
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
|
|
||||||
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matchUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
|
private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
|
||||||
super.markRequestAsProcessingSubRequest(theRequestDetails);
|
super.markRequestAsProcessingSubRequest(theRequestDetails);
|
||||||
try {
|
try {
|
||||||
|
@ -742,20 +755,6 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
return Integer.toString(theStatusCode) + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
|
return Integer.toString(theStatusCode) + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BaseServerResponseExceptionHolder
|
|
||||||
{
|
|
||||||
private BaseServerResponseException myException;
|
|
||||||
|
|
||||||
public BaseServerResponseException getException() {
|
|
||||||
return myException;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setException(BaseServerResponseException myException) {
|
|
||||||
this.myException = myException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
/**
|
/**
|
||||||
* Transaction Order, per the spec:
|
* Transaction Order, per the spec:
|
||||||
*
|
*
|
||||||
|
@ -859,4 +858,19 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
|
||||||
|
private static class BaseServerResponseExceptionHolder
|
||||||
|
{
|
||||||
|
private BaseServerResponseException myException;
|
||||||
|
|
||||||
|
public BaseServerResponseException getException() {
|
||||||
|
return myException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(BaseServerResponseException myException) {
|
||||||
|
this.myException = myException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,9 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
final Date updateTime = new Date();
|
final Date updateTime = new Date();
|
||||||
|
|
||||||
final Set<IdType> allIds = new LinkedHashSet<IdType>();
|
final Set<IdType> allIds = new LinkedHashSet<>();
|
||||||
final Map<IdType, IdType> idSubstitutions = new HashMap<IdType, IdType>();
|
final Map<IdType, IdType> idSubstitutions = new HashMap<>();
|
||||||
final Map<IdType, DaoMethodOutcome> idToPersistedOutcome = new HashMap<IdType, DaoMethodOutcome>();
|
final Map<IdType, DaoMethodOutcome> idToPersistedOutcome = new HashMap<>();
|
||||||
|
|
||||||
// Do all entries have a verb?
|
// Do all entries have a verb?
|
||||||
for (int i = 0; i < theRequest.getEntry().size(); i++) {
|
for (int i = 0; i < theRequest.getEntry().size(); i++) {
|
||||||
|
@ -193,8 +193,8 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
* we want the GET processing to use the final indexing state
|
* we want the GET processing to use the final indexing state
|
||||||
*/
|
*/
|
||||||
final Bundle response = new Bundle();
|
final Bundle response = new Bundle();
|
||||||
List<BundleEntryComponent> getEntries = new ArrayList<BundleEntryComponent>();
|
List<BundleEntryComponent> getEntries = new ArrayList<>();
|
||||||
final IdentityHashMap<BundleEntryComponent, Integer> originalRequestOrder = new IdentityHashMap<Bundle.BundleEntryComponent, Integer>();
|
final IdentityHashMap<BundleEntryComponent, Integer> originalRequestOrder = new IdentityHashMap<>();
|
||||||
for (int i = 0; i < theRequest.getEntry().size(); i++) {
|
for (int i = 0; i < theRequest.getEntry().size(); i++) {
|
||||||
originalRequestOrder.put(theRequest.getEntry().get(i), i);
|
originalRequestOrder.put(theRequest.getEntry().get(i), i);
|
||||||
response.addEntry();
|
response.addEntry();
|
||||||
|
@ -316,13 +316,13 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date updateTime, Set<IdType> allIds,
|
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdType> theAllIds,
|
||||||
Map<IdType, IdType> idSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, Bundle response, IdentityHashMap<BundleEntryComponent, Integer> originalRequestOrder, List<BundleEntryComponent> theEntries) {
|
Map<IdType, IdType> theIdSubstitutions, Map<IdType, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<BundleEntryComponent, Integer> theOriginalRequestOrder, List<BundleEntryComponent> theEntries) {
|
||||||
Set<String> deletedResources = new HashSet<String>();
|
Set<String> deletedResources = new HashSet<>();
|
||||||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
List<DeleteConflict> deleteConflicts = new ArrayList<>();
|
||||||
Map<BundleEntryComponent, ResourceTable> entriesToProcess = new IdentityHashMap<BundleEntryComponent, ResourceTable>();
|
Map<BundleEntryComponent, ResourceTable> entriesToProcess = new IdentityHashMap<>();
|
||||||
Set<ResourceTable> nonUpdatedEntities = new HashSet<ResourceTable>();
|
Set<ResourceTable> nonUpdatedEntities = new HashSet<>();
|
||||||
Map<String, Class<? extends IBaseResource>> conditionalRequestUrls = new HashMap<String, Class<? extends IBaseResource>>();
|
Map<String, Class<? extends IBaseResource>> conditionalRequestUrls = new HashMap<>();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop through the request and process any entries of type
|
* Loop through the request and process any entries of type
|
||||||
|
@ -341,7 +341,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
nextResourceId = res.getIdElement();
|
nextResourceId = res.getIdElement();
|
||||||
|
|
||||||
if (nextResourceId.hasIdPart() == false) {
|
if (!nextResourceId.hasIdPart()) {
|
||||||
if (isNotBlank(nextReqEntry.getFullUrl())) {
|
if (isNotBlank(nextReqEntry.getFullUrl())) {
|
||||||
nextResourceId = new IdType(nextReqEntry.getFullUrl());
|
nextResourceId = new IdType(nextReqEntry.getFullUrl());
|
||||||
}
|
}
|
||||||
|
@ -360,12 +360,12 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||||
*/
|
*/
|
||||||
if (isPlaceholder(nextResourceId)) {
|
if (isPlaceholder(nextResourceId)) {
|
||||||
if (!allIds.add(nextResourceId)) {
|
if (!theAllIds.add(nextResourceId)) {
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextResourceId));
|
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextResourceId));
|
||||||
}
|
}
|
||||||
} else if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
|
} else if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
|
||||||
IdType nextId = nextResourceId.toUnqualifiedVersionless();
|
IdType nextId = nextResourceId.toUnqualifiedVersionless();
|
||||||
if (!allIds.add(nextId)) {
|
if (!theAllIds.add(nextId)) {
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
|
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +375,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
||||||
|
|
||||||
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
|
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
|
||||||
BundleEntryComponent nextRespEntry = response.getEntry().get(originalRequestOrder.get(nextReqEntry));
|
BundleEntryComponent nextRespEntry = theResponse.getEntry().get(theOriginalRequestOrder.get(nextReqEntry));
|
||||||
|
|
||||||
switch (verb) {
|
switch (verb) {
|
||||||
case POST: {
|
case POST: {
|
||||||
|
@ -385,10 +385,10 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
res.setId((String) null);
|
res.setId((String) null);
|
||||||
DaoMethodOutcome outcome;
|
DaoMethodOutcome outcome;
|
||||||
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
||||||
if (nextResourceId != null) {
|
if (nextResourceId != null) {
|
||||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, theIdToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
||||||
}
|
}
|
||||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||||
if (outcome.getCreated() == false) {
|
if (outcome.getCreated() == false) {
|
||||||
|
@ -418,7 +418,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String matchUrl = parts.getResourceType() + '?' + parts.getParams();
|
String matchUrl = parts.getResourceType() + '?' + parts.getParams();
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(matchUrl, deleteConflicts, theRequestDetails);
|
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(matchUrl, deleteConflicts, theRequestDetails);
|
||||||
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
||||||
for (ResourceTable deleted : allDeleted) {
|
for (ResourceTable deleted : allDeleted) {
|
||||||
|
@ -459,14 +459,14 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
} else {
|
} else {
|
||||||
matchUrl = parts.getResourceType();
|
matchUrl = parts.getResourceType();
|
||||||
}
|
}
|
||||||
matchUrl = performIdSubstitutionsInMatchUrl(idSubstitutions, matchUrl);
|
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
|
||||||
outcome = resourceDao.update(res, matchUrl, false, theRequestDetails);
|
outcome = resourceDao.update(res, matchUrl, false, theRequestDetails);
|
||||||
if (Boolean.TRUE.equals(outcome.getCreated())) {
|
if (Boolean.TRUE.equals(outcome.getCreated())) {
|
||||||
conditionalRequestUrls.put(matchUrl, res.getClass());
|
conditionalRequestUrls.put(matchUrl, res.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, theIdToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
|
||||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -499,20 +499,21 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FhirTerser terser = getContext().newTerser();
|
FhirTerser terser = getContext().newTerser();
|
||||||
for (DaoMethodOutcome nextOutcome : idToPersistedOutcome.values()) {
|
for (DaoMethodOutcome nextOutcome : theIdToPersistedOutcome.values()) {
|
||||||
IBaseResource nextResource = nextOutcome.getResource();
|
IBaseResource nextResource = nextOutcome.getResource();
|
||||||
if (nextResource == null) {
|
if (nextResource == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// References
|
||||||
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, IBaseReference.class);
|
||||||
for (IBaseReference nextRef : allRefs) {
|
for (IBaseReference nextRef : allRefs) {
|
||||||
IIdType nextId = nextRef.getReferenceElement();
|
IIdType nextId = nextRef.getReferenceElement();
|
||||||
if (!nextId.hasIdPart()) {
|
if (!nextId.hasIdPart()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (idSubstitutions.containsKey(nextId)) {
|
if (theIdSubstitutions.containsKey(nextId)) {
|
||||||
IdType newId = idSubstitutions.get(nextId);
|
IdType newId = theIdSubstitutions.get(nextId);
|
||||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||||
nextRef.setReference(newId.getValue());
|
nextRef.setReference(newId.getValue());
|
||||||
} else if (nextId.getValue().startsWith("urn:")) {
|
} else if (nextId.getValue().startsWith("urn:")) {
|
||||||
|
@ -522,11 +523,27 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URIs
|
||||||
|
List<UriType> allUris = terser.getAllPopulatedChildElementsOfType(nextResource, UriType.class);
|
||||||
|
for (UriType nextRef : allUris) {
|
||||||
|
if (nextRef instanceof IIdType) {
|
||||||
|
continue; // No substitution on the resource ID itself!
|
||||||
|
}
|
||||||
|
IdType nextUriString = new IdType(nextRef.getValueAsString());
|
||||||
|
if (theIdSubstitutions.containsKey(nextUriString)) {
|
||||||
|
IdType newId = theIdSubstitutions.get(nextUriString);
|
||||||
|
ourLog.info(" * Replacing resource ref {} with {}", nextUriString, newId);
|
||||||
|
nextRef.setValue(newId.getValue());
|
||||||
|
} else {
|
||||||
|
ourLog.debug(" * Reference [{}] does not exist in bundle", nextUriString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
|
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
|
||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, shouldUpdate, false, updateTime, false, true);
|
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, shouldUpdate, false, theUpdateTime, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,8 +565,8 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdType next : allIds) {
|
for (IdType next : theAllIds) {
|
||||||
IdType replacement = idSubstitutions.get(next);
|
IdType replacement = theIdSubstitutions.get(next);
|
||||||
if (replacement == null) {
|
if (replacement == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,9 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
|
||||||
@Qualifier("myDiagnosticReportDaoDstu2")
|
@Qualifier("myDiagnosticReportDaoDstu2")
|
||||||
protected IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
|
protected IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myBinaryDaoDstu2")
|
||||||
|
protected IFhirResourceDao<Binary> myBinaryDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myEncounterDaoDstu2")
|
@Qualifier("myEncounterDaoDstu2")
|
||||||
protected IFhirResourceDao<Encounter> myEncounterDao;
|
protected IFhirResourceDao<Encounter> myEncounterDao;
|
||||||
// @PersistenceContext()
|
// @PersistenceContext()
|
||||||
|
|
|
@ -1,37 +1,23 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu2;
|
package ca.uhn.fhir.jpa.dao.dstu2;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.springframework.transaction.TransactionStatus;
|
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.entity.*;
|
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||||
import ca.uhn.fhir.model.api.*;
|
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.base.composite.BaseCodingDt;
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.*;
|
import ca.uhn.fhir.model.dstu2.composite.AttachmentDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.*;
|
import ca.uhn.fhir.model.dstu2.resource.*;
|
||||||
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.*;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.*;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryResponse;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||||
|
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.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.UriDt;
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
@ -40,101 +26,28 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.*;
|
import ca.uhn.fhir.rest.server.exceptions.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* See #638
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testTransactionBug638() throws Exception {
|
|
||||||
String input = loadClasspath("/bug638.xml");
|
|
||||||
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, request);
|
|
||||||
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
|
||||||
|
|
||||||
assertEquals(18, resp.getEntry().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWhichFailsPersistsNothing() {
|
|
||||||
|
|
||||||
// Run a transaction which points to that practitioner
|
|
||||||
// in a field that isn't allowed to refer to a practitioner
|
|
||||||
Bundle input = new Bundle();
|
|
||||||
input.setType(BundleTypeEnum.TRANSACTION);
|
|
||||||
|
|
||||||
Patient pt = new Patient();
|
|
||||||
pt.setId("PT");
|
|
||||||
pt.setActive(true);
|
|
||||||
pt.addName().addFamily("FAMILY");
|
|
||||||
input.addEntry()
|
|
||||||
.setResource(pt)
|
|
||||||
.getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Patient/PT");
|
|
||||||
|
|
||||||
Observation obs = new Observation();
|
|
||||||
obs.setId("OBS");
|
|
||||||
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
|
||||||
obs.addPerformer().setReference("Practicioner/AAAAA");
|
|
||||||
input.addEntry()
|
|
||||||
.setResource(obs)
|
|
||||||
.getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Observation/OBS");
|
|
||||||
|
|
||||||
try {
|
|
||||||
mySystemDao.transaction(mySrd, input);
|
|
||||||
fail();
|
|
||||||
} catch (UnprocessableEntityException e) {
|
|
||||||
assertThat(e.getMessage(), containsString("Resource type 'Practicioner' is not valid for this path"));
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(myResourceTableDao.findAll(), empty());
|
|
||||||
assertThat(myResourceIndexedSearchParamStringDao.findAll(), empty());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Per a message on the mailing list
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithPostDoesntUpdate() throws Exception {
|
|
||||||
|
|
||||||
// First bundle (name is Joshua)
|
|
||||||
|
|
||||||
String input = IOUtils.toString(getClass().getResource("/dstu3-post1.xml"), StandardCharsets.UTF_8);
|
|
||||||
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
|
||||||
Bundle response = mySystemDao.transaction(mySrd, request);
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
|
||||||
|
|
||||||
assertEquals(1, response.getEntry().size());
|
|
||||||
assertEquals("201 Created", response.getEntry().get(0).getResponse().getStatus());
|
|
||||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
|
||||||
String id = response.getEntry().get(0).getResponse().getLocation();
|
|
||||||
|
|
||||||
// Now the second (name is Adam, shouldn't get used)
|
|
||||||
|
|
||||||
input = IOUtils.toString(getClass().getResource("/dstu3-post2.xml"), StandardCharsets.UTF_8);
|
|
||||||
request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
|
||||||
response = mySystemDao.transaction(mySrd, request);
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
|
||||||
|
|
||||||
assertEquals(1, response.getEntry().size());
|
|
||||||
assertEquals("200 OK", response.getEntry().get(0).getResponse().getStatus());
|
|
||||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
|
||||||
String id2 = response.getEntry().get(0).getResponse().getLocation();
|
|
||||||
assertEquals(id, id2);
|
|
||||||
|
|
||||||
Patient patient = myPatientDao.read(new IdType(id), mySrd);
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
|
|
||||||
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSystemMetaOperation() {
|
public void testSystemMetaOperation() {
|
||||||
|
|
||||||
|
@ -266,6 +179,20 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #638
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTransactionBug638() throws Exception {
|
||||||
|
String input = loadClasspath("/bug638.xml");
|
||||||
|
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, request);
|
||||||
|
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
assertEquals(18, resp.getEntry().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||||
|
@ -1379,6 +1306,42 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWhichFailsPersistsNothing() {
|
||||||
|
|
||||||
|
// Run a transaction which points to that practitioner
|
||||||
|
// in a field that isn't allowed to refer to a practitioner
|
||||||
|
Bundle input = new Bundle();
|
||||||
|
input.setType(BundleTypeEnum.TRANSACTION);
|
||||||
|
|
||||||
|
Patient pt = new Patient();
|
||||||
|
pt.setId("PT");
|
||||||
|
pt.setActive(true);
|
||||||
|
pt.addName().addFamily("FAMILY");
|
||||||
|
input.addEntry()
|
||||||
|
.setResource(pt)
|
||||||
|
.getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Patient/PT");
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setId("OBS");
|
||||||
|
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||||
|
obs.addPerformer().setReference("Practicioner/AAAAA");
|
||||||
|
input.addEntry()
|
||||||
|
.setResource(obs)
|
||||||
|
.getRequest().setMethod(HTTPVerbEnum.PUT).setUrl("Observation/OBS");
|
||||||
|
|
||||||
|
try {
|
||||||
|
mySystemDao.transaction(mySrd, input);
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Resource type 'Practicioner' is not valid for this path"));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(myResourceTableDao.findAll(), empty());
|
||||||
|
assertThat(myResourceIndexedSearchParamStringDao.findAll(), empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From a message from David Hay
|
* From a message from David Hay
|
||||||
*/
|
*/
|
||||||
|
@ -1535,6 +1498,42 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
assertEquals(id0.toUnqualifiedVersionless().getValue(), app2.getParticipant().get(1).getActor().getReference().getValue());
|
assertEquals(id0.toUnqualifiedVersionless().getValue(), app2.getParticipant().get(1).getActor().getReference().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per a message on the mailing list
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithPostDoesntUpdate() throws Exception {
|
||||||
|
|
||||||
|
// First bundle (name is Joshua)
|
||||||
|
|
||||||
|
String input = IOUtils.toString(getClass().getResource("/dstu3-post1.xml"), StandardCharsets.UTF_8);
|
||||||
|
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
Bundle response = mySystemDao.transaction(mySrd, request);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||||
|
|
||||||
|
assertEquals(1, response.getEntry().size());
|
||||||
|
assertEquals("201 Created", response.getEntry().get(0).getResponse().getStatus());
|
||||||
|
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||||
|
String id = response.getEntry().get(0).getResponse().getLocation();
|
||||||
|
|
||||||
|
// Now the second (name is Adam, shouldn't get used)
|
||||||
|
|
||||||
|
input = IOUtils.toString(getClass().getResource("/dstu3-post2.xml"), StandardCharsets.UTF_8);
|
||||||
|
request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
response = mySystemDao.transaction(mySrd, request);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||||
|
|
||||||
|
assertEquals(1, response.getEntry().size());
|
||||||
|
assertEquals("200 OK", response.getEntry().get(0).getResponse().getStatus());
|
||||||
|
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||||
|
String id2 = response.getEntry().get(0).getResponse().getLocation();
|
||||||
|
assertEquals(id, id2);
|
||||||
|
|
||||||
|
Patient patient = myPatientDao.read(new IdType(id), mySrd);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
|
||||||
|
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
|
@ -1626,6 +1625,47 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is not the correct way to do it, but we'll allow it to be lenient
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithRelativeOidIdsQualified() throws Exception {
|
||||||
|
Bundle res = new Bundle();
|
||||||
|
res.setType(BundleTypeEnum.TRANSACTION);
|
||||||
|
|
||||||
|
Patient p1 = new Patient();
|
||||||
|
p1.setId("urn:oid:0.1.2.3");
|
||||||
|
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
||||||
|
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
||||||
|
|
||||||
|
Observation o1 = new Observation();
|
||||||
|
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
||||||
|
o1.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Observation o2 = new Observation();
|
||||||
|
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
||||||
|
o2.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, res);
|
||||||
|
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
||||||
|
assertEquals(3, resp.getEntry().size());
|
||||||
|
|
||||||
|
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdDt(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
|
||||||
|
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
||||||
|
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
||||||
|
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||||
|
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
|
@ -1728,45 +1768,52 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
|
||||||
* This is not the correct way to do it, but we'll allow it to be lenient
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithRelativeOidIdsQualified() throws Exception {
|
public void testTransactionWithReplacement() {
|
||||||
Bundle res = new Bundle();
|
byte[] bytes = new byte[] {0, 1, 2, 3, 4};
|
||||||
res.setType(BundleTypeEnum.TRANSACTION);
|
|
||||||
|
|
||||||
Patient p1 = new Patient();
|
Binary binary = new Binary();
|
||||||
p1.setId("urn:oid:0.1.2.3");
|
binary.setId(IdDt.newRandomUuid());
|
||||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
binary.setContent(bytes);
|
||||||
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
|
binary.setContentType("application/pdf");
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
DiagnosticReport dr = new DiagnosticReport();
|
||||||
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
dr.setId(IdDt.newRandomUuid());
|
||||||
o1.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
|
|
||||||
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
|
||||||
|
|
||||||
Observation o2 = new Observation();
|
AttachmentDt attachment = new AttachmentDt();
|
||||||
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
attachment.setContentType("application/pdf");
|
||||||
o2.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
|
attachment.getUrlElement().setValueAsString(binary.getId().getValueAsString()); // this one has substitution
|
||||||
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
dr.addPresentedForm(attachment);
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, res);
|
AttachmentDt attachment2 = new AttachmentDt();
|
||||||
|
attachment2.getUrlElement().setValueAsString(IdDt.newRandomUuid().getValue()); // this one has no subscitution
|
||||||
|
dr.addPresentedForm(attachment2);
|
||||||
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
Bundle transactionBundle = new Bundle();
|
||||||
|
transactionBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||||
|
|
||||||
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
Entry binaryEntry = new Bundle.Entry();
|
||||||
assertEquals(3, resp.getEntry().size());
|
binaryEntry.setResource(binary).setFullUrl(binary.getId()).getRequest().setUrl("Binary").setMethod(HTTPVerbEnum.POST);
|
||||||
|
transactionBundle.addEntry(binaryEntry);
|
||||||
|
|
||||||
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdDt(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
Entry drEntry = new Entry();
|
||||||
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
drEntry.setResource(dr).setFullUrl(dr.getId()).getRequest().setUrl("DiagnosticReport").setMethod(HTTPVerbEnum.POST);
|
||||||
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
transactionBundle.addEntry(drEntry);
|
||||||
|
|
||||||
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(transactionBundle));
|
||||||
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
|
||||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
|
||||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
|
||||||
|
|
||||||
|
Bundle transactionResp = mySystemDao.transaction(mySrd, transactionBundle);
|
||||||
|
|
||||||
|
assertEquals(2, transactionResp.getEntry().size());
|
||||||
|
|
||||||
|
// Validate Binary
|
||||||
|
binary = myBinaryDao.read(new IdType(transactionResp.getEntry().get(0).getResponse().getLocation()));
|
||||||
|
assertArrayEquals(bytes, binary.getContent());
|
||||||
|
|
||||||
|
// Validate DiagnosticReport
|
||||||
|
dr = myDiagnosticReportDao.read(new IdType(transactionResp.getEntry().get(1).getResponse().getLocation()));
|
||||||
|
assertEquals(binary.getIdElement().toUnqualifiedVersionless().getValue(), dr.getPresentedForm().get(0).getUrl());
|
||||||
|
assertEquals(attachment2.getUrl(), dr.getPresentedForm().get(1).getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
|
|
@ -99,6 +99,9 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
@Qualifier("myDiagnosticReportDaoDstu3")
|
@Qualifier("myDiagnosticReportDaoDstu3")
|
||||||
protected IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
|
protected IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myBinaryDaoDstu3")
|
||||||
|
protected IFhirResourceDao<Binary> myBinaryDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myEncounterDaoDstu3")
|
@Qualifier("myEncounterDaoDstu3")
|
||||||
protected IFhirResourceDao<Encounter> myEncounterDao;
|
protected IFhirResourceDao<Encounter> myEncounterDao;
|
||||||
// @PersistenceContext()
|
// @PersistenceContext()
|
||||||
|
|
|
@ -2520,7 +2520,6 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithReferenceResource() {
|
public void testTransactionWithReferenceResource() {
|
||||||
Bundle request = new Bundle();
|
Bundle request = new Bundle();
|
||||||
|
@ -2548,7 +2547,6 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
assertEquals(1, found.size().intValue());
|
assertEquals(1, found.size().intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
|
@ -2602,6 +2600,33 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
assertNotEquals(medOrderId1, medOrderId2);
|
assertNotEquals(medOrderId1, medOrderId2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithReferenceUuid() {
|
||||||
|
Bundle request = new Bundle();
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
p.setId(IdType.newRandomUuid());
|
||||||
|
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId());
|
||||||
|
|
||||||
|
Observation o = new Observation();
|
||||||
|
o.getCode().setText("Some Observation");
|
||||||
|
o.getSubject().setReference(p.getId());
|
||||||
|
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, request);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue();
|
||||||
|
assertThat(patientId, startsWith("Patient/"));
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.setLoadSynchronous(true);
|
||||||
|
params.add("subject", new ReferenceParam(patientId));
|
||||||
|
IBundleProvider found = myObservationDao.search(params);
|
||||||
|
assertEquals(1, found.size().intValue());
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
|
@ -2704,34 +2729,6 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithReferenceUuid() {
|
|
||||||
Bundle request = new Bundle();
|
|
||||||
|
|
||||||
Patient p = new Patient();
|
|
||||||
p.setActive(true);
|
|
||||||
p.setId(IdType.newRandomUuid());
|
|
||||||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId());
|
|
||||||
|
|
||||||
Observation o = new Observation();
|
|
||||||
o.getCode().setText("Some Observation");
|
|
||||||
o.getSubject().setReference(p.getId());
|
|
||||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, request);
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
|
||||||
|
|
||||||
String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue();
|
|
||||||
assertThat(patientId, startsWith("Patient/"));
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.setLoadSynchronous(true);
|
|
||||||
params.add("subject", new ReferenceParam(patientId));
|
|
||||||
IBundleProvider found = myObservationDao.search(params);
|
|
||||||
assertEquals(1, found.size().intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithRelativeOidIds() throws Exception {
|
public void testTransactionWithRelativeOidIds() throws Exception {
|
||||||
Bundle res = new Bundle();
|
Bundle res = new Bundle();
|
||||||
|
@ -2811,6 +2808,52 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithReplacement() {
|
||||||
|
byte[] bytes = new byte[] {0, 1, 2, 3, 4};
|
||||||
|
|
||||||
|
Binary binary = new Binary();
|
||||||
|
binary.setId(IdType.newRandomUuid());
|
||||||
|
binary.setContent(bytes);
|
||||||
|
binary.setContentType("application/pdf");
|
||||||
|
|
||||||
|
DiagnosticReport dr = new DiagnosticReport();
|
||||||
|
dr.setId(IdDt.newRandomUuid());
|
||||||
|
|
||||||
|
Attachment attachment = new Attachment();
|
||||||
|
attachment.setContentType("application/pdf");
|
||||||
|
attachment.setUrl(binary.getId()); // this one has substitution
|
||||||
|
dr.addPresentedForm(attachment);
|
||||||
|
|
||||||
|
Attachment attachment2 = new Attachment();
|
||||||
|
attachment2.setUrl(IdType.newRandomUuid().getValue()); // this one has no subscitution
|
||||||
|
dr.addPresentedForm(attachment2);
|
||||||
|
|
||||||
|
Bundle transactionBundle = new Bundle();
|
||||||
|
transactionBundle.setType(BundleType.TRANSACTION);
|
||||||
|
|
||||||
|
Bundle.BundleEntryComponent binaryEntry = new Bundle.BundleEntryComponent();
|
||||||
|
binaryEntry.setResource(binary).setFullUrl(binary.getId()).getRequest().setUrl("Binary").setMethod(Bundle.HTTPVerb.POST);
|
||||||
|
transactionBundle.addEntry(binaryEntry);
|
||||||
|
|
||||||
|
Bundle.BundleEntryComponent drEntry = new Bundle.BundleEntryComponent();
|
||||||
|
drEntry.setResource(dr).setFullUrl(dr.getId()).getRequest().setUrl("DiagnosticReport").setMethod(Bundle.HTTPVerb.POST);
|
||||||
|
transactionBundle.addEntry(drEntry);
|
||||||
|
|
||||||
|
Bundle transactionResp = mySystemDao.transaction(mySrd, transactionBundle);
|
||||||
|
|
||||||
|
assertEquals(2, transactionResp.getEntry().size());
|
||||||
|
|
||||||
|
// Validate Binary
|
||||||
|
binary = myBinaryDao.read(new IdType(transactionResp.getEntry().get(0).getResponse().getLocation()));
|
||||||
|
assertArrayEquals(bytes, binary.getContent());
|
||||||
|
|
||||||
|
// Validate DiagnosticReport
|
||||||
|
dr = myDiagnosticReportDao.read(new IdType(transactionResp.getEntry().get(1).getResponse().getLocation()));
|
||||||
|
assertEquals(binary.getIdElement().toUnqualifiedVersionless().getValue(), dr.getPresentedForm().get(0).getUrl());
|
||||||
|
assertEquals(attachment2.getUrl(), dr.getPresentedForm().get(1).getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #467
|
* See #467
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -157,6 +157,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
protected DatabaseBackedPagingProvider myPagingProvider;
|
protected DatabaseBackedPagingProvider myPagingProvider;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myBinaryDaoR4")
|
||||||
|
protected IFhirResourceDao<Binary> myBinaryDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myPatientDaoR4")
|
@Qualifier("myPatientDaoR4")
|
||||||
protected IFhirResourceDaoPatient<Patient> myPatientDao;
|
protected IFhirResourceDaoPatient<Patient> myPatientDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -159,8 +159,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
for (BundleEntryComponent nextEntry : theBundle.getEntry()) {
|
for (BundleEntryComponent nextEntry : theBundle.getEntry()) {
|
||||||
if (nextEntry.getResource() != null && theType.isAssignableFrom(nextEntry.getResource().getClass())) {
|
if (nextEntry.getResource() != null && theType.isAssignableFrom(nextEntry.getResource().getClass())) {
|
||||||
if (count == theIndex) {
|
if (count == theIndex) {
|
||||||
T t = (T) nextEntry.getResource();
|
return (T) nextEntry.getResource();
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -729,78 +728,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithCircularReferences() {
|
|
||||||
Bundle request = new Bundle();
|
|
||||||
request.setType(BundleType.TRANSACTION);
|
|
||||||
|
|
||||||
Encounter enc = new Encounter();
|
|
||||||
enc.addIdentifier().setSystem("A").setValue("1");
|
|
||||||
enc.setId(IdType.newRandomUuid());
|
|
||||||
|
|
||||||
Condition cond = new Condition();
|
|
||||||
cond.addIdentifier().setSystem("A").setValue("2");
|
|
||||||
cond.setId(IdType.newRandomUuid());
|
|
||||||
|
|
||||||
enc.addDiagnosis().getCondition().setReference(cond.getId());
|
|
||||||
cond.getContext().setReference(enc.getId());
|
|
||||||
|
|
||||||
request
|
|
||||||
.addEntry()
|
|
||||||
.setFullUrl(enc.getId())
|
|
||||||
.setResource(enc)
|
|
||||||
.getRequest()
|
|
||||||
.setMethod(HTTPVerb.PUT)
|
|
||||||
.setUrl("Encounter?identifier=A|1");
|
|
||||||
request
|
|
||||||
.addEntry()
|
|
||||||
.setFullUrl(cond.getId())
|
|
||||||
.setResource(cond)
|
|
||||||
.getRequest()
|
|
||||||
.setMethod(HTTPVerb.PUT)
|
|
||||||
.setUrl("Condition?identifier=A|2");
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, request);
|
|
||||||
assertEquals(2, resp.getEntry().size());
|
|
||||||
|
|
||||||
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
respEntry = resp.getEntry().get(1);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithCircularReferences2() throws IOException {
|
|
||||||
Bundle request = loadResourceFromClasspath(Bundle.class, "/dstu3_transaction.xml");
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, request);
|
|
||||||
assertEquals(3, resp.getEntry().size());
|
|
||||||
|
|
||||||
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
respEntry = resp.getEntry().get(1);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithCircularReferences3() throws IOException {
|
|
||||||
Bundle request = loadResourceFromClasspath(Bundle.class, "/dstu3_transaction2.xml");
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, request);
|
|
||||||
assertEquals(3, resp.getEntry().size());
|
|
||||||
|
|
||||||
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
respEntry = resp.getEntry().get(1);
|
|
||||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCreateInlineMatchUrlWithOneMatchLastUpdated() {
|
public void testTransactionCreateInlineMatchUrlWithOneMatchLastUpdated() {
|
||||||
Bundle request = new Bundle();
|
Bundle request = new Bundle();
|
||||||
|
@ -2260,6 +2187,78 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithCircularReferences() {
|
||||||
|
Bundle request = new Bundle();
|
||||||
|
request.setType(BundleType.TRANSACTION);
|
||||||
|
|
||||||
|
Encounter enc = new Encounter();
|
||||||
|
enc.addIdentifier().setSystem("A").setValue("1");
|
||||||
|
enc.setId(IdType.newRandomUuid());
|
||||||
|
|
||||||
|
Condition cond = new Condition();
|
||||||
|
cond.addIdentifier().setSystem("A").setValue("2");
|
||||||
|
cond.setId(IdType.newRandomUuid());
|
||||||
|
|
||||||
|
enc.addDiagnosis().getCondition().setReference(cond.getId());
|
||||||
|
cond.getContext().setReference(enc.getId());
|
||||||
|
|
||||||
|
request
|
||||||
|
.addEntry()
|
||||||
|
.setFullUrl(enc.getId())
|
||||||
|
.setResource(enc)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerb.PUT)
|
||||||
|
.setUrl("Encounter?identifier=A|1");
|
||||||
|
request
|
||||||
|
.addEntry()
|
||||||
|
.setFullUrl(cond.getId())
|
||||||
|
.setResource(cond)
|
||||||
|
.getRequest()
|
||||||
|
.setMethod(HTTPVerb.PUT)
|
||||||
|
.setUrl("Condition?identifier=A|2");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, request);
|
||||||
|
assertEquals(2, resp.getEntry().size());
|
||||||
|
|
||||||
|
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
respEntry = resp.getEntry().get(1);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithCircularReferences2() throws IOException {
|
||||||
|
Bundle request = loadResourceFromClasspath(Bundle.class, "/dstu3_transaction.xml");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, request);
|
||||||
|
assertEquals(3, resp.getEntry().size());
|
||||||
|
|
||||||
|
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
respEntry = resp.getEntry().get(1);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithCircularReferences3() throws IOException {
|
||||||
|
Bundle request = loadResourceFromClasspath(Bundle.class, "/dstu3_transaction2.xml");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, request);
|
||||||
|
assertEquals(3, resp.getEntry().size());
|
||||||
|
|
||||||
|
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
respEntry = resp.getEntry().get(1);
|
||||||
|
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithIfMatch() {
|
public void testTransactionWithIfMatch() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -2719,6 +2718,44 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
assertEquals(1, found.size().intValue());
|
assertEquals(1, found.size().intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithRelativeOidIds() throws Exception {
|
||||||
|
Bundle res = new Bundle();
|
||||||
|
res.setType(BundleType.TRANSACTION);
|
||||||
|
|
||||||
|
Patient p1 = new Patient();
|
||||||
|
p1.setId("urn:oid:0.1.2.3");
|
||||||
|
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
||||||
|
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
|
||||||
|
|
||||||
|
Observation o1 = new Observation();
|
||||||
|
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
||||||
|
o1.setSubject(new Reference("urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerb.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Observation o2 = new Observation();
|
||||||
|
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
||||||
|
o2.setSubject(new Reference("urn:oid:0.1.2.3"));
|
||||||
|
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerb.POST).setUrl("Observation");
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(mySrd, res);
|
||||||
|
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
assertEquals(BundleType.TRANSACTIONRESPONSE, resp.getTypeElement().getValue());
|
||||||
|
assertEquals(3, resp.getEntry().size());
|
||||||
|
|
||||||
|
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdType(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdType(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdType(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
||||||
|
|
||||||
|
o1 = myObservationDao.read(new IdType(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
||||||
|
o2 = myObservationDao.read(new IdType(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
||||||
|
assertThat(o1.getSubject().getReferenceElement().getValue(), endsWith("Patient/" + p1.getIdElement().getIdPart()));
|
||||||
|
assertThat(o2.getSubject().getReferenceElement().getValue(), endsWith("Patient/" + p1.getIdElement().getIdPart()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
|
@ -2821,44 +2858,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransactionWithRelativeOidIds() throws Exception {
|
|
||||||
Bundle res = new Bundle();
|
|
||||||
res.setType(BundleType.TRANSACTION);
|
|
||||||
|
|
||||||
Patient p1 = new Patient();
|
|
||||||
p1.setId("urn:oid:0.1.2.3");
|
|
||||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds01");
|
|
||||||
res.addEntry().setResource(p1).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
|
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
|
||||||
o1.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds02");
|
|
||||||
o1.setSubject(new Reference("urn:oid:0.1.2.3"));
|
|
||||||
res.addEntry().setResource(o1).getRequest().setMethod(HTTPVerb.POST).setUrl("Observation");
|
|
||||||
|
|
||||||
Observation o2 = new Observation();
|
|
||||||
o2.addIdentifier().setSystem("system").setValue("testTransactionWithRelativeOidIds03");
|
|
||||||
o2.setSubject(new Reference("urn:oid:0.1.2.3"));
|
|
||||||
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerb.POST).setUrl("Observation");
|
|
||||||
|
|
||||||
Bundle resp = mySystemDao.transaction(mySrd, res);
|
|
||||||
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
|
||||||
|
|
||||||
assertEquals(BundleType.TRANSACTIONRESPONSE, resp.getTypeElement().getValue());
|
|
||||||
assertEquals(3, resp.getEntry().size());
|
|
||||||
|
|
||||||
assertTrue(resp.getEntry().get(0).getResponse().getLocation(), new IdType(resp.getEntry().get(0).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdType(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdType(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
|
|
||||||
|
|
||||||
o1 = myObservationDao.read(new IdType(resp.getEntry().get(1).getResponse().getLocation()), mySrd);
|
|
||||||
o2 = myObservationDao.read(new IdType(resp.getEntry().get(2).getResponse().getLocation()), mySrd);
|
|
||||||
assertThat(o1.getSubject().getReferenceElement().getValue(), endsWith("Patient/" + p1.getIdElement().getIdPart()));
|
|
||||||
assertThat(o2.getSubject().getReferenceElement().getValue(), endsWith("Patient/" + p1.getIdElement().getIdPart()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is not the correct way to do it, but we'll allow it to be lenient
|
* This is not the correct way to do it, but we'll allow it to be lenient
|
||||||
*/
|
*/
|
||||||
|
@ -2900,6 +2899,52 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithReplacement() {
|
||||||
|
byte[] bytes = new byte[] {0, 1, 2, 3, 4};
|
||||||
|
|
||||||
|
Binary binary = new Binary();
|
||||||
|
binary.setId(IdType.newRandomUuid());
|
||||||
|
binary.setContent(bytes);
|
||||||
|
binary.setContentType("application/pdf");
|
||||||
|
|
||||||
|
DiagnosticReport dr = new DiagnosticReport();
|
||||||
|
dr.setId(IdDt.newRandomUuid());
|
||||||
|
|
||||||
|
Attachment attachment = new Attachment();
|
||||||
|
attachment.setContentType("application/pdf");
|
||||||
|
attachment.setUrl(binary.getId()); // this one has substitution
|
||||||
|
dr.addPresentedForm(attachment);
|
||||||
|
|
||||||
|
Attachment attachment2 = new Attachment();
|
||||||
|
attachment2.setUrl(IdType.newRandomUuid().getValue()); // this one has no subscitution
|
||||||
|
dr.addPresentedForm(attachment2);
|
||||||
|
|
||||||
|
Bundle transactionBundle = new Bundle();
|
||||||
|
transactionBundle.setType(BundleType.TRANSACTION);
|
||||||
|
|
||||||
|
Bundle.BundleEntryComponent binaryEntry = new Bundle.BundleEntryComponent();
|
||||||
|
binaryEntry.setResource(binary).setFullUrl(binary.getId()).getRequest().setUrl("Binary").setMethod(Bundle.HTTPVerb.POST);
|
||||||
|
transactionBundle.addEntry(binaryEntry);
|
||||||
|
|
||||||
|
Bundle.BundleEntryComponent drEntry = new Bundle.BundleEntryComponent();
|
||||||
|
drEntry.setResource(dr).setFullUrl(dr.getId()).getRequest().setUrl("DiagnosticReport").setMethod(Bundle.HTTPVerb.POST);
|
||||||
|
transactionBundle.addEntry(drEntry);
|
||||||
|
|
||||||
|
Bundle transactionResp = mySystemDao.transaction(mySrd, transactionBundle);
|
||||||
|
|
||||||
|
assertEquals(2, transactionResp.getEntry().size());
|
||||||
|
|
||||||
|
// Validate Binary
|
||||||
|
binary = myBinaryDao.read(new IdType(transactionResp.getEntry().get(0).getResponse().getLocation()));
|
||||||
|
assertArrayEquals(bytes, binary.getContent());
|
||||||
|
|
||||||
|
// Validate DiagnosticReport
|
||||||
|
dr = myDiagnosticReportDao.read(new IdType(transactionResp.getEntry().get(1).getResponse().getLocation()));
|
||||||
|
assertEquals(binary.getIdElement().toUnqualifiedVersionless().getValue(), dr.getPresentedForm().get(0).getUrl());
|
||||||
|
assertEquals(attachment2.getUrl(), dr.getPresentedForm().get(1).getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #467
|
* See #467
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -144,6 +144,12 @@
|
||||||
Avoid an endless loop of reindexing in JPA if a SearchParameter is
|
Avoid an endless loop of reindexing in JPA if a SearchParameter is
|
||||||
created which indexed the SearchParameter resource itself
|
created which indexed the SearchParameter resource itself
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add" issue="854">
|
||||||
|
JPA server now performs temporary/placeholder ID substitution processing on elements in
|
||||||
|
resources which are of type "URI" in addition to the current substitution for
|
||||||
|
elements of type "Reference". Thanks to GitHub user @t4deon for supplying
|
||||||
|
a testcase!
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.2.0" date="2018-01-13">
|
<release version="3.2.0" date="2018-01-13">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue