Some work on collection processing
This commit is contained in:
parent
76cd3f6b47
commit
cca49425ae
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -43,10 +43,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.*;
|
||||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
|
@ -86,17 +83,6 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DaoRegistry myDaoRegistry;
|
private DaoRegistry myDaoRegistry;
|
||||||
|
|
||||||
public static boolean isPlaceholder(IIdType theId) {
|
|
||||||
if (theId != null && theId.getValue() != null) {
|
|
||||||
return theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toStatusString(int theStatusCode) {
|
|
||||||
return Integer.toString(theStatusCode) + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateEntryWithOperationOutcome(BaseServerResponseException caughtEx, BUNDLEENTRY nextEntry) {
|
private void populateEntryWithOperationOutcome(BaseServerResponseException caughtEx, BUNDLEENTRY nextEntry) {
|
||||||
myVersionAdapter.populateEntryWithOperationOutcome(caughtEx, nextEntry);
|
myVersionAdapter.populateEntryWithOperationOutcome(caughtEx, nextEntry);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +150,6 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
return defaultString(theId.getValue()).startsWith(URN_PREFIX);
|
return defaultString(theId.getValue()).startsWith(URN_PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setDao(BaseHapiFhirDao theDao) {
|
public void setDao(BaseHapiFhirDao theDao) {
|
||||||
myDao = theDao;
|
myDao = theDao;
|
||||||
}
|
}
|
||||||
|
@ -188,6 +173,40 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BUNDLE collection(final RequestDetails theRequestDetails, BUNDLE theRequest) {
|
||||||
|
String transactionType = myVersionAdapter.getBundleType(theRequest);
|
||||||
|
|
||||||
|
if (!org.hl7.fhir.r4.model.Bundle.BundleType.COLLECTION.toCode().equals(transactionType)) {
|
||||||
|
throw new InvalidRequestException("Can not process collection Bundle of type: " + transactionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info("Beginning storing collection with {} resources", myVersionAdapter.getEntries(theRequest).size());
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||||
|
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||||
|
|
||||||
|
BUNDLE resp = myVersionAdapter.createBundle(org.hl7.fhir.r4.model.Bundle.BundleType.BATCHRESPONSE.toCode());
|
||||||
|
|
||||||
|
List<IBaseResource> resources = new ArrayList<>();
|
||||||
|
for (final BUNDLEENTRY nextRequestEntry : myVersionAdapter.getEntries(theRequest)) {
|
||||||
|
IBaseResource resource = myVersionAdapter.getResource(nextRequestEntry);
|
||||||
|
resources.add(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
BUNDLE transactionBundle = myVersionAdapter.createBundle("transaction");
|
||||||
|
for (IBaseResource next : resources) {
|
||||||
|
BUNDLEENTRY entry = myVersionAdapter.addEntry(transactionBundle);
|
||||||
|
myVersionAdapter.setResource(entry, next);
|
||||||
|
myVersionAdapter.setRequestVerb(entry, "PUT");
|
||||||
|
myVersionAdapter.setRequestUrl(entry, next.getIdElement().toUnqualifiedVersionless().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction(theRequestDetails, transactionBundle);
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
private BUNDLE batch(final RequestDetails theRequestDetails, BUNDLE theRequest) {
|
private BUNDLE batch(final RequestDetails theRequestDetails, BUNDLE theRequest) {
|
||||||
ourLog.info("Beginning batch with {} resources", myVersionAdapter.getEntries(theRequest).size());
|
ourLog.info("Beginning batch with {} resources", myVersionAdapter.getEntries(theRequest).size());
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
|
@ -255,6 +274,7 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
validateDependencies();
|
validateDependencies();
|
||||||
|
|
||||||
String transactionType = myVersionAdapter.getBundleType(theRequest);
|
String transactionType = myVersionAdapter.getBundleType(theRequest);
|
||||||
|
|
||||||
if (org.hl7.fhir.r4.model.Bundle.BundleType.BATCH.toCode().equals(transactionType)) {
|
if (org.hl7.fhir.r4.model.Bundle.BundleType.BATCH.toCode().equals(transactionType)) {
|
||||||
return batch(theRequestDetails, theRequest);
|
return batch(theRequestDetails, theRequest);
|
||||||
}
|
}
|
||||||
|
@ -846,18 +866,10 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
String getEntryRequestIfNoneMatch(BUNDLEENTRY theEntry);
|
String getEntryRequestIfNoneMatch(BUNDLEENTRY theEntry);
|
||||||
|
|
||||||
void setResponseOutcome(BUNDLEENTRY theEntry, IBaseOperationOutcome theOperationOutcome);
|
void setResponseOutcome(BUNDLEENTRY theEntry, IBaseOperationOutcome theOperationOutcome);
|
||||||
}
|
|
||||||
|
|
||||||
private static class BaseServerResponseExceptionHolder {
|
void setRequestVerb(BUNDLEENTRY theEntry, String theVerb);
|
||||||
private BaseServerResponseException myException;
|
|
||||||
|
|
||||||
public BaseServerResponseException getException() {
|
void setRequestUrl(BUNDLEENTRY theEntry, String theUrl);
|
||||||
return myException;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setException(BaseServerResponseException myException) {
|
|
||||||
this.myException = myException;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -963,4 +975,27 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class BaseServerResponseExceptionHolder {
|
||||||
|
private BaseServerResponseException myException;
|
||||||
|
|
||||||
|
public BaseServerResponseException getException() {
|
||||||
|
return myException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(BaseServerResponseException myException) {
|
||||||
|
this.myException = myException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPlaceholder(IIdType theId) {
|
||||||
|
if (theId != null && theId.getValue() != null) {
|
||||||
|
return theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toStatusString(int theStatusCode) {
|
||||||
|
return Integer.toString(theStatusCode) + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,4 +150,14 @@ public class TransactionProcessorVersionAdapterDstu3 implements TransactionProce
|
||||||
theEntry.getResponse().setOutcome((Resource) theOperationOutcome);
|
theEntry.getResponse().setOutcome((Resource) theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequestVerb(Bundle.BundleEntryComponent theEntry, String theVerb) {
|
||||||
|
theEntry.getRequest().setMethod(Bundle.HTTPVerb.fromCode(theVerb));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequestUrl(Bundle.BundleEntryComponent theEntry, String theUrl) {
|
||||||
|
theEntry.getRequest().setUrl(theUrl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -23,12 +23,12 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
|
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
|
||||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
|
||||||
import org.hl7.fhir.r4.model.Resource;
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
|
import org.hl7.fhir.r4.model.Resource;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -150,4 +150,14 @@ public class TransactionProcessorVersionAdapterR4 implements TransactionProcesso
|
||||||
theEntry.getResponse().setOutcome((Resource) theOperationOutcome);
|
theEntry.getResponse().setOutcome((Resource) theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequestVerb(Bundle.BundleEntryComponent theEntry, String theVerb) {
|
||||||
|
theEntry.getRequest().setMethod(Bundle.HTTPVerb.fromCode(theVerb));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequestUrl(Bundle.BundleEntryComponent theEntry, String theUrl) {
|
||||||
|
theEntry.getRequest().setUrl(theUrl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.GZipUtil;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
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.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.parser.LenientErrorHandler;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
@ -52,6 +54,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
public void after() {
|
public void after() {
|
||||||
myDaoConfig.setAllowInlineMatchUrlReferences(false);
|
myDaoConfig.setAllowInlineMatchUrlReferences(false);
|
||||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||||
|
myDaoConfig.setProcessCollectionsAsBatch(new DaoConfig().isProcessCollectionsAsBatch());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -322,6 +325,22 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessCollectionAsBatch() throws IOException {
|
||||||
|
myDaoConfig.setProcessCollectionsAsBatch(true);
|
||||||
|
|
||||||
|
byte[] inputBytes = IOUtils.toByteArray(getClass().getResourceAsStream("/dstu3/Reilly_Libby_73.json.gz"));
|
||||||
|
String input = GZipUtil.decompress(inputBytes);
|
||||||
|
Bundle bundle = myFhirCtx.newJsonParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(Bundle.class, input);
|
||||||
|
ourLog.info("Bundle has {} resources", bundle);
|
||||||
|
|
||||||
|
Bundle output = mySystemDao.transaction(mySrd, bundle);
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #410
|
* See #410
|
||||||
*/
|
*/
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue