Some work on collection processing

This commit is contained in:
James Agnew 2018-11-08 08:56:51 -05:00
parent 76cd3f6b47
commit cca49425ae
5 changed files with 107 additions and 33 deletions

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -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.BaseResourceReturningMethodBinding;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.util.*;
import com.google.common.collect.ArrayListMultimap;
import org.apache.commons.lang3.Validate;
import org.apache.http.NameValuePair;
@ -86,17 +83,6 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
@Autowired
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) {
myVersionAdapter.populateEntryWithOperationOutcome(caughtEx, nextEntry);
}
@ -164,7 +150,6 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
return defaultString(theId.getValue()).startsWith(URN_PREFIX);
}
public void setDao(BaseHapiFhirDao 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) {
ourLog.info("Beginning batch with {} resources", myVersionAdapter.getEntries(theRequest).size());
long start = System.currentTimeMillis();
@ -255,6 +274,7 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
validateDependencies();
String transactionType = myVersionAdapter.getBundleType(theRequest);
if (org.hl7.fhir.r4.model.Bundle.BundleType.BATCH.toCode().equals(transactionType)) {
return batch(theRequestDetails, theRequest);
}
@ -846,18 +866,10 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
String getEntryRequestIfNoneMatch(BUNDLEENTRY theEntry);
void setResponseOutcome(BUNDLEENTRY theEntry, IBaseOperationOutcome theOperationOutcome);
}
private static class BaseServerResponseExceptionHolder {
private BaseServerResponseException myException;
void setRequestVerb(BUNDLEENTRY theEntry, String theVerb);
public BaseServerResponseException getException() {
return myException;
}
public void setException(BaseServerResponseException myException) {
this.myException = myException;
}
void setRequestUrl(BUNDLEENTRY theEntry, String theUrl);
}
/**
@ -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));
}
}

View File

@ -150,4 +150,14 @@ public class TransactionProcessorVersionAdapterDstu3 implements TransactionProce
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);
}
}

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao.r4;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -23,12 +23,12 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
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.instance.model.api.IBaseOperationOutcome;
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.List;
@ -150,4 +150,14 @@ public class TransactionProcessorVersionAdapterR4 implements TransactionProcesso
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);
}
}

View File

@ -2,12 +2,14 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
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.entity.ResourceTag;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
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.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -52,6 +54,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
public void after() {
myDaoConfig.setAllowInlineMatchUrlReferences(false);
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
myDaoConfig.setProcessCollectionsAsBatch(new DaoConfig().isProcessCollectionsAsBatch());
}
@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
*/