val = myMatchResourceUrlService.processMatchUrl(matchUrl, resType, theRequestDetails);
- if (val.size() > 1) {
- throw new InvalidRequestException(
- "Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
- }
- }
- }
- }
-
- for (IdDt next : theAllIds) {
- IdDt replacement = theIdSubstitutions.get(next);
- if (replacement == null) {
- continue;
- }
- if (replacement.equals(next)) {
- continue;
- }
- ourLog.debug("Placeholder resource ID \"{}\" was replaced with permanent ID \"{}\"", next, replacement);
- }
- }
-
- private String extractTransactionUrlOrThrowException(Entry nextEntry, HTTPVerbEnum verb) {
- String url = nextEntry.getRequest().getUrl();
- if (isBlank(url)) {
- throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionMissingUrl", verb.name()));
- }
- return url;
- }
-
- /**
- * This method is called for nested bundles (e.g. if we received a transaction with an entry that
- * was a GET search, this method is called on the bundle for the search result, that will be placed in the
- * outer bundle). This method applies the _summary and _content parameters to the output of
- * that bundle.
- *
- * TODO: This isn't the most efficient way of doing this.. hopefully we can come up with something better in the future.
- */
- private IBaseResource filterNestedBundle(RequestDetails theRequestDetails, IBaseResource theResource) {
- IParser p = getContext().newJsonParser();
- RestfulServerUtils.configureResponseParser(theRequestDetails, p);
- return p.parseResource(theResource.getClass(), p.encodeResourceToString(theResource));
- }
@Override
public MetaDt metaGetOperation(RequestDetails theRequestDetails) {
@@ -589,31 +49,6 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao {
return retVal;
}
- private IFhirResourceDao extends IBaseResource> toDao(UrlParts theParts, String theVerb, String theUrl) {
- RuntimeResourceDefinition resType;
- try {
- resType = getContext().getResourceDefinition(theParts.getResourceType());
- } catch (DataFormatException e) {
- String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theVerb, theUrl);
- throw new InvalidRequestException(msg);
- }
- IFhirResourceDao extends IBaseResource> dao = null;
- if (resType != null) {
- dao = this.myDaoRegistry.getResourceDaoOrNull(resType.getImplementingClass());
- }
- if (dao == null) {
- String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theVerb, theUrl);
- throw new InvalidRequestException(msg);
- }
-
- // if (theParts.getResourceId() == null && theParts.getParams() == null) {
- // String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theVerb, theUrl);
- // throw new InvalidRequestException(msg);
- // }
-
- return dao;
- }
-
protected MetaDt toMetaDt(Collection tagDefinitions) {
MetaDt retVal = new MetaDt();
for (TagDefinition next : tagDefinitions) {
@@ -632,105 +67,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao {
return retVal;
}
- @Transactional(propagation = Propagation.NEVER)
- @Override
- public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
- if (theRequestDetails != null) {
- ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
- notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
- }
-
- String actionName = "Transaction";
- return transaction((ServletRequestDetails) theRequestDetails, theRequest, actionName);
- }
-
- private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
- markRequestAsProcessingSubRequest(theRequestDetails);
- try {
- return doTransaction(theRequestDetails, theRequest, theActionName);
- } finally {
- clearRequestAsProcessingSubRequest(theRequestDetails);
- }
- }
-
- private static void handleTransactionCreateOrUpdateOutcome(Map idSubstitutions, Map idToPersistedOutcome, IdDt nextResourceId, DaoMethodOutcome outcome,
- Entry newEntry, String theResourceType, IResource theRes) {
- IdDt newId = (IdDt) outcome.getId().toUnqualifiedVersionless();
- IdDt resourceId = isPlaceholder(nextResourceId) ? nextResourceId : nextResourceId.toUnqualifiedVersionless();
- if (newId.equals(resourceId) == false) {
- idSubstitutions.put(resourceId, newId);
- if (isPlaceholder(resourceId)) {
- /*
- * The correct way for substitution IDs to be is to be with no resource type, but we'll accept the qualified kind too just to be lenient.
- */
- idSubstitutions.put(new IdDt(theResourceType + '/' + resourceId.getValue()), newId);
- }
- }
- idToPersistedOutcome.put(newId, outcome);
- if (outcome.getCreated().booleanValue()) {
- newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_201_CREATED));
- } else {
- newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
- }
- newEntry.getResponse().setLastModified(ResourceMetadataKeyEnum.UPDATED.get(theRes));
- }
-
- private static boolean isPlaceholder(IdDt theId) {
- if (theId.getValue() != null) {
- return theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:");
- }
- return false;
- }
-
- private static String toStatusString(int theStatusCode) {
- return theStatusCode + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
- }
-
@Override
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
}
-
- /**
- * Transaction Order, per the spec:
- *
- * Process any DELETE interactions
- * Process any POST interactions
- * Process any PUT interactions
- * Process any GET interactions
- */
- public class TransactionSorter implements Comparator {
-
- @Override
- public int compare(Entry theO1, Entry theO2) {
- int o1 = toOrder(theO1);
- int o2 = toOrder(theO2);
-
- return o1 - o2;
- }
-
- private int toOrder(Entry theO1) {
- int o1 = 0;
- if (theO1.getRequest().getMethodElement().getValueAsEnum() != null) {
- switch (theO1.getRequest().getMethodElement().getValueAsEnum()) {
- case DELETE:
- o1 = 1;
- break;
- case POST:
- o1 = 2;
- break;
- case PUT:
- o1 = 3;
- break;
- case GET:
- o1 = 4;
- break;
- }
- }
- return o1;
- }
-
- }
-
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/LegacySearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/LegacySearchBuilder.java
index 4f3a2de40f5..25a5dbbc89d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/LegacySearchBuilder.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/LegacySearchBuilder.java
@@ -42,7 +42,6 @@ import ca.uhn.fhir.jpa.entity.ResourceSearchView;
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
-import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@@ -51,9 +50,8 @@ import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.lastn.IElasticsearchSvc;
-import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
+import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper;
import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper;
import ca.uhn.fhir.jpa.util.BaseIterator;
@@ -483,8 +481,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
return orders;
}
- RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceName);
- RuntimeSearchParam param = mySearchParamRegistry.getSearchParamByName(resourceDef, theSort.getParamName());
+ RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(myResourceName, theSort.getParamName());
if (param == null) {
throw new InvalidRequestException("Unknown sort parameter '" + theSort.getParamName() + "'");
}
@@ -757,7 +754,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
String paramName = nextInclude.getParamName();
if (isNotBlank(paramName)) {
- param = mySearchParamRegistry.getSearchParamByName(def, paramName);
+ param = mySearchParamRegistry.getActiveSearchParam(resType, paramName);
} else {
param = null;
}
@@ -876,7 +873,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
// Since we're going to remove elements below
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
- List activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
+ List activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
if (activeUniqueSearchParams.size() > 0) {
StringBuilder sb = new StringBuilder();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessorVersionAdapterDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessorVersionAdapterDstu2.java
new file mode 100644
index 00000000000..b1b87a079e1
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessorVersionAdapterDstu2.java
@@ -0,0 +1,171 @@
+package ca.uhn.fhir.jpa.dao;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2021 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
+import ca.uhn.fhir.model.dstu2.resource.Bundle;
+import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
+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.dstu2.valueset.IssueTypeEnum;
+import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
+import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
+import org.hl7.fhir.exceptions.FHIRException;
+import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+import java.util.Date;
+import java.util.List;
+
+public class TransactionProcessorVersionAdapterDstu2 implements TransactionProcessor.ITransactionProcessorVersionAdapter {
+ @Override
+ public void setResponseStatus(Bundle.Entry theBundleEntry, String theStatus) {
+ theBundleEntry.getResponse().setStatus(theStatus);
+ }
+
+ @Override
+ public void setResponseLastModified(Bundle.Entry theBundleEntry, Date theLastModified) {
+ theBundleEntry.getResponse().setLastModified(theLastModified, TemporalPrecisionEnum.MILLI);
+ }
+
+ @Override
+ public void setResource(Bundle.Entry theBundleEntry, IBaseResource theResource) {
+ theBundleEntry.setResource((IResource) theResource);
+ }
+
+ @Override
+ public IBaseResource getResource(Bundle.Entry theBundleEntry) {
+ return theBundleEntry.getResource();
+ }
+
+ @Override
+ public String getBundleType(Bundle theRequest) {
+ if (theRequest.getType() == null) {
+ return null;
+ }
+ return theRequest.getTypeElement().getValue();
+ }
+
+ @Override
+ public void populateEntryWithOperationOutcome(BaseServerResponseException theCaughtEx, Bundle.Entry theEntry) {
+ OperationOutcome oo = new OperationOutcome();
+ oo.addIssue()
+ .setSeverity(IssueSeverityEnum.ERROR)
+ .setDiagnostics(theCaughtEx.getMessage())
+ .setCode(IssueTypeEnum.EXCEPTION);
+ theEntry.setResource(oo);
+ }
+
+ @Override
+ public Bundle createBundle(String theBundleType) {
+ Bundle resp = new Bundle();
+ try {
+ resp.setType(BundleTypeEnum.forCode(theBundleType));
+ } catch (FHIRException theE) {
+ throw new InternalErrorException("Unknown bundle type: " + theBundleType);
+ }
+ return resp;
+ }
+
+ @Override
+ public List getEntries(Bundle theRequest) {
+ return theRequest.getEntry();
+ }
+
+ @Override
+ public void addEntry(Bundle theBundle, Bundle.Entry theEntry) {
+ theBundle.addEntry(theEntry);
+ }
+
+ @Override
+ public Bundle.Entry addEntry(Bundle theBundle) {
+ return theBundle.addEntry();
+ }
+
+ @Override
+ public String getEntryRequestVerb(FhirContext theContext, Bundle.Entry theEntry) {
+ String retVal = null;
+ HTTPVerbEnum value = theEntry.getRequest().getMethodElement().getValueAsEnum();
+ if (value != null) {
+ retVal = value.getCode();
+ }
+ return retVal;
+ }
+
+ @Override
+ public String getFullUrl(Bundle.Entry theEntry) {
+ return theEntry.getFullUrl();
+ }
+
+ @Override
+ public String getEntryIfNoneExist(Bundle.Entry theEntry) {
+ return theEntry.getRequest().getIfNoneExist();
+ }
+
+ @Override
+ public String getEntryRequestUrl(Bundle.Entry theEntry) {
+ return theEntry.getRequest().getUrl();
+ }
+
+ @Override
+ public void setResponseLocation(Bundle.Entry theEntry, String theResponseLocation) {
+ theEntry.getResponse().setLocation(theResponseLocation);
+ }
+
+ @Override
+ public void setResponseETag(Bundle.Entry theEntry, String theEtag) {
+ theEntry.getResponse().setEtag(theEtag);
+ }
+
+ @Override
+ public String getEntryRequestIfMatch(Bundle.Entry theEntry) {
+ return theEntry.getRequest().getIfMatch();
+ }
+
+ @Override
+ public String getEntryRequestIfNoneExist(Bundle.Entry theEntry) {
+ return theEntry.getRequest().getIfNoneExist();
+ }
+
+ @Override
+ public String getEntryRequestIfNoneMatch(Bundle.Entry theEntry) {
+ return theEntry.getRequest().getIfNoneMatch();
+ }
+
+ @Override
+ public void setResponseOutcome(Bundle.Entry theEntry, IBaseOperationOutcome theOperationOutcome) {
+ theEntry.setResource((IResource) theOperationOutcome);
+ }
+
+ @Override
+ public void setRequestVerb(Bundle.Entry theEntry, String theVerb) {
+ theEntry.getRequest().setMethod(HTTPVerbEnum.forCode(theVerb));
+ }
+
+ @Override
+ public void setRequestUrl(Bundle.Entry theEntry, String theUrl) {
+ theEntry.getRequest().setUrl(theUrl);
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkExportJobDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkExportJobDao.java
index 708425d5fdb..c5bf0ddf606 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkExportJobDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkExportJobDao.java
@@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.dao.data;
-import ca.uhn.fhir.jpa.bulk.model.BulkJobStatusEnum;
+import ca.uhn.fhir.jpa.bulk.export.model.BulkExportJobStatusEnum;
import ca.uhn.fhir.jpa.entity.BulkExportJobEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@@ -38,13 +38,13 @@ public interface IBulkExportJobDao extends JpaRepository findByJobId(@Param("jobid") String theUuid);
@Query("SELECT j FROM BulkExportJobEntity j WHERE j.myStatus = :status")
- Slice findByStatus(Pageable thePage, @Param("status") BulkJobStatusEnum theSubmitted);
+ Slice findByStatus(Pageable thePage, @Param("status") BulkExportJobStatusEnum theSubmitted);
@Query("SELECT j FROM BulkExportJobEntity j WHERE j.myExpiry < :cutoff")
Slice findByExpiry(Pageable thePage, @Param("cutoff") Date theCutoff);
@Query("SELECT j FROM BulkExportJobEntity j WHERE j.myRequest = :request AND j.myCreated > :createdAfter AND j.myStatus <> :status ORDER BY j.myCreated DESC")
- Slice findExistingJob(Pageable thePage, @Param("request") String theRequest, @Param("createdAfter") Date theCreatedAfter, @Param("status") BulkJobStatusEnum theNotStatus);
+ Slice findExistingJob(Pageable thePage, @Param("request") String theRequest, @Param("createdAfter") Date theCreatedAfter, @Param("status") BulkExportJobStatusEnum theNotStatus);
@Modifying
@Query("DELETE FROM BulkExportJobEntity t")
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobDao.java
new file mode 100644
index 00000000000..dccaa953eb8
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobDao.java
@@ -0,0 +1,40 @@
+package ca.uhn.fhir.jpa.dao.data;
+
+import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobStatusEnum;
+import ca.uhn.fhir.jpa.entity.BulkImportJobEntity;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Slice;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.Optional;
+
+/*
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2021 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+public interface IBulkImportJobDao extends JpaRepository {
+
+ @Query("SELECT j FROM BulkImportJobEntity j WHERE j.myJobId = :jobid")
+ Optional findByJobId(@Param("jobid") String theUuid);
+
+ @Query("SELECT j FROM BulkImportJobEntity j WHERE j.myStatus = :status")
+ Slice findByStatus(Pageable thePage, @Param("status") BulkImportJobStatusEnum theStatus);
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobFileDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobFileDao.java
new file mode 100644
index 00000000000..c53e49f95a4
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBulkImportJobFileDao.java
@@ -0,0 +1,43 @@
+package ca.uhn.fhir.jpa.dao.data;
+
+import ca.uhn.fhir.jpa.entity.BulkImportJobEntity;
+import ca.uhn.fhir.jpa.entity.BulkImportJobFileEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+import java.util.Optional;
+
+/*
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2021 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+public interface IBulkImportJobFileDao extends JpaRepository {
+
+ @Query("SELECT f FROM BulkImportJobFileEntity f WHERE f.myJob.myJobId = :jobId ORDER BY f.myFileSequence ASC")
+ List findAllForJob(@Param("jobId") String theJobId);
+
+ @Query("SELECT f FROM BulkImportJobFileEntity f WHERE f.myJob = :job AND f.myFileSequence = :fileIndex")
+ Optional findForJob(@Param("job") BulkImportJobEntity theJob, @Param("fileIndex") int theFileIndex);
+
+ @Query("SELECT f.myId FROM BulkImportJobFileEntity f WHERE f.myJob.myJobId = :jobId ORDER BY f.myFileSequence ASC")
+ List findAllIdsForJob(@Param("jobId") String theJobId);
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
index 53814c503b7..16834facbe2 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
@@ -58,4 +58,13 @@ public interface IMdmLinkDao extends JpaRepository {
Long getSourcePid();
}
+ @Query("SELECT ml.myGoldenResourcePid as goldenPid, ml.mySourcePid as sourcePid " +
+ "FROM MdmLink ml " +
+ "INNER JOIN MdmLink ml2 " +
+ "on ml.myGoldenResourcePid=ml2.myGoldenResourcePid " +
+ "WHERE ml2.mySourcePid=:sourcePid " +
+ "AND ml2.myMatchResult=:matchResult " +
+ "AND ml.myMatchResult=:matchResult")
+ List expandPidsBySourcePidAndMatchResult(@Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum);
+
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java
index 6145e033b33..968ba695414 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java
@@ -47,42 +47,21 @@ import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao implements IFhirResourceDaoValueSet {
@Override
- public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
+ public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails);
- return expand(source, theFilter);
+ return expand(source, theOptions);
}
@Override
- public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) {
- org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails);
- return expand(source, theFilter, theOffset, theCount);
- }
-
- @Override
- public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter) {
- org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, theUri, theFilter);
- return ValueSet30_40.convertValueSet(canonicalOutput);
- }
-
- @Override
- public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) {
- ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
- org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, theUri, theFilter);
- return ValueSet30_40.convertValueSet(canonicalOutput);
- }
-
- @Override
- public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter) {
+ public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, ValueSetExpansionOptions theOptions) {
org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource);
- org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, canonicalInput, theFilter);
+ org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput);
return ValueSet30_40.convertValueSet(canonicalOutput);
}
@Override
- public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter, int theOffset, int theCount) {
- ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
- org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource);
- org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, canonicalInput, theFilter);
+ public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
+ org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri);
return ValueSet30_40.convertValueSet(canonicalOutput);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java
index 0af11e3a082..96019ae6a21 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java
@@ -22,18 +22,13 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
-import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import org.hl7.fhir.dstu3.model.Bundle;
-import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.instance.model.api.IBaseBundle;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.persistence.TypedQuery;
@@ -42,14 +37,10 @@ import java.util.List;
public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao {
- @Autowired
- private TransactionProcessor myTransactionProcessor;
-
@Override
@PostConstruct
public void start() {
super.start();
- myTransactionProcessor.setDao(this);
}
@Override
@@ -88,12 +79,5 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao {
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
}
- @Transactional(propagation = Propagation.NEVER)
- @Override
- public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
- return myTransactionProcessor.transaction(theRequestDetails, theRequest);
- }
-
-
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java
index 5da2372c9b6..e012ee235ad 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java
@@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.dao.expunge;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
+import ca.uhn.fhir.jpa.entity.BulkImportJobEntity;
+import ca.uhn.fhir.jpa.entity.BulkImportJobFileEntity;
import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchInclude;
@@ -123,6 +125,8 @@ public class ExpungeEverythingService {
counter.addAndGet(expungeEverythingByType(NpmPackageVersionEntity.class));
counter.addAndGet(expungeEverythingByType(NpmPackageEntity.class));
counter.addAndGet(expungeEverythingByType(SearchParamPresent.class));
+ counter.addAndGet(expungeEverythingByType(BulkImportJobFileEntity.class));
+ counter.addAndGet(expungeEverythingByType(BulkImportJobEntity.class));
counter.addAndGet(expungeEverythingByType(ForcedId.class));
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamDate.class));
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamNumber.class));
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java
index a8795a47d4f..d28ba15b5d1 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java
@@ -380,6 +380,29 @@ public class IdHelperService {
}
}
+ /**
+ *
+ * Given a set of PIDs, return a set of public FHIR Resource IDs.
+ * This function will resolve a forced ID if it resolves, and if it fails to resolve to a forced it, will just return the pid
+ * Example:
+ * Let's say we have Patient/1(pid == 1), Patient/pat1 (pid == 2), Patient/3 (pid == 3), their pids would resolve as follows:
+ *
+ * [1,2,3] -> ["1","pat1","3"]
+ *
+ * @param thePids The Set of pids you would like to resolve to external FHIR Resource IDs.
+ * @return A Set of strings representing the FHIR IDs of the pids.
+ */
+ public Set translatePidsToFhirResourceIds(Set thePids) {
+ Map> pidToForcedIdMap = translatePidsToForcedIds(thePids);
+
+ //If the result of the translation is an empty optional, it means there is no forced id, and we can use the PID as the resource ID.
+ Set resolvedResourceIds = pidToForcedIdMap.entrySet().stream()
+ .map(entry -> entry.getValue().isPresent() ? entry.getValue().get() : entry.getKey().toString())
+ .collect(Collectors.toSet());
+
+ return resolvedResourceIds;
+
+ }
public Map> translatePidsToForcedIds(Set thePids) {
Map> retVal = new HashMap<>(myMemoryCacheService.getAllPresent(MemoryCacheService.CacheEnum.FORCED_ID, thePids));
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
index f16ae6e2fac..228b0d62303 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
@@ -25,26 +25,26 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
-import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
-import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
-import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
+import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
-import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
+import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
+import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.UrlUtil;
import com.google.common.annotations.VisibleForTesting;
@@ -148,13 +148,14 @@ public class SearchParamWithInlineReferencesExtractor {
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
final String resourceType = theEntity.getResourceType();
- List uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
+ List uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
- for (JpaRuntimeSearchParam next : uniqueSearchParams) {
+ for (RuntimeSearchParam next : uniqueSearchParams) {
List