From ee7b19fe3cada761d0c086267d0f8f01a793aa60 Mon Sep 17 00:00:00 2001 From: Frank Tao <38163583+frankjtao@users.noreply.github.com> Date: Mon, 11 Jan 2021 20:36:54 -0500 Subject: [PATCH 1/4] Fixed the migration scripts (#2283) --- .../jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index 236230b1679..8cc9d077f6d 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -106,11 +106,19 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { pkg.addIndex("20210109.5", "IDX_SP_QNTY_NRML_HASH_SYSUN").unique(false).withColumns("HASH_IDENTITY_SYS_UNITS","SP_VALUE"); pkg.addIndex("20210109.6", "IDX_SP_QNTY_NRML_UPDATED").unique(false).withColumns("SP_UPDATED"); pkg.addIndex("20210109.7", "IDX_SP_QNTY_NRML_RESID").unique(false).withColumns("RES_ID"); - //pkg.addForeignKey("20210109.9", "FK_QNTY_NRML_RESID").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID"); //-- Link to the resourceTable version.onTable("HFJ_RESOURCE").addColumn("20210109.10", "SP_QUANTITY_NRML_PRESENT").nullable().type(ColumnTypeEnum.BOOLEAN); + //-- Fixed the partition and fk + Builder.BuilderWithTableName nrmlTable = version.onTable("HFJ_SPIDX_QUANTITY_NRML"); + nrmlTable.addColumn("20210111.1", "PARTITION_ID").nullable().type(ColumnTypeEnum.INT); + nrmlTable.addColumn("20210111.2", "PARTITION_DATE").nullable().type(ColumnTypeEnum.DATE_ONLY); + // - The fk name is generated from Hibernate, have to use this name here + nrmlTable + .addForeignKey("20210111.3", "FKRCJOVMUH5KC0O6FVBLE319PYV") + .toColumn("RES_ID") + .references("HFJ_RESOURCE", "RES_ID"); } protected void init520() { From 520400d6eabe2236deb2ce6a913d2623c97c757f Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Mon, 11 Jan 2021 20:42:41 -0500 Subject: [PATCH 2/4] added IPagingProvider.canSearchByOffset() (#2281) * init rev * added IPagingProvider.canSearchByOffset() consolidated parameters in bundle link methods * fix refactoring error * add @Nonnull to BundleLinks parameter * null check * fix test * cleanup * fix refactoring * final cleanup * review feedback * review feedback * review feedback --- hapi-fhir-base/pom.xml | 6 ++ .../ca/uhn/fhir/rest/api/BundleLinks.java | 62 ++++++++++++++++ .../api/IVersionSpecificBundleFactory.java | 8 +- .../ca/uhn/fhir/cli/ExampleDataUploader.java | 4 +- .../BaseHttpClientInvocationWithContents.java | 47 ++++-------- .../uhn/hapi/fhir/docs/IncludesExamples.java | 2 +- .../search/DatabaseBackedPagingProvider.java | 3 +- .../fhir/rest/api/server/IRestfulServer.java | 3 + .../rest/server/FifoMemoryPagingProvider.java | 6 +- .../uhn/fhir/rest/server/IPagingProvider.java | 13 ++++ .../fhir/rest/server/RestfulServerUtils.java | 47 +++++++----- .../BaseResourceReturningMethodBinding.java | 73 ++++++++++--------- .../rest/server/method/PageMethodBinding.java | 14 ++-- .../rest/server/Dstu2_1BundleFactory.java | 44 +++++++---- .../provider/dstu2/Dstu2BundleFactory.java | 56 +++++++++----- .../hapi/rest/server/Dstu3BundleFactory.java | 44 +++++++---- .../dstu2hl7org/Dstu2Hl7OrgBundleFactory.java | 34 ++++++--- .../r4/hapi/rest/server/R4BundleFactory.java | 44 +++++++---- .../server/PagingUsingNamedPagesR4Test.java | 1 + .../r5/hapi/rest/server/R5BundleFactory.java | 44 +++++++---- 20 files changed, 370 insertions(+), 185 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 8fa1625806e..9f5b7f81f45 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -116,6 +116,12 @@ true + + + com.google.code.findbugs + jsr305 + + org.awaitility awaitility diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java new file mode 100644 index 00000000000..c482e15f7d9 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java @@ -0,0 +1,62 @@ +package ca.uhn.fhir.rest.api; + +import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.model.valueset.BundleTypeEnum; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class BundleLinks { + public final String serverBase; + public final boolean prettyPrint; + public final BundleTypeEnum bundleType; + private final List includes; + + private String self; + private String next; + private String prev; + + public BundleLinks(String theServerBase, Set theIncludes, boolean thePrettyPrint, BundleTypeEnum theBundleType) { + serverBase = theServerBase; + includes = theIncludes == null ? null : new ArrayList<>(theIncludes); + prettyPrint = thePrettyPrint; + bundleType = theBundleType; + } + + public String getSelf() { + return self; + } + + public BundleLinks setSelf(String theSelf) { + self = theSelf; + return this; + } + + public String getNext() { + return next; + } + + public BundleLinks setNext(String theNext) { + next = theNext; + return this; + } + + public String getPrev() { + return prev; + } + + public BundleLinks setPrev(String thePrev) { + prev = thePrev; + return this; + } + + public Collection getIncludes() { + if (includes == null) { + return null; + } + return Collections.unmodifiableList(includes); + } +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/IVersionSpecificBundleFactory.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/IVersionSpecificBundleFactory.java index 0f402207e9d..229d160b5f5 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/IVersionSpecificBundleFactory.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/IVersionSpecificBundleFactory.java @@ -26,6 +26,7 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -38,17 +39,17 @@ public interface IVersionSpecificBundleFactory { void addResourcesToBundle(List theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set theIncludes); - void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType theLastUpdated); + void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated); IBaseResource getResourceBundle(); /** - * @deprecated This was deprecated in HAPI FHIR 4.1.0 as it provides duplicate functionality to the {@link #addRootPropertiesToBundle(String, String, String, String, String, Integer, BundleTypeEnum, IPrimitiveType)} + * @deprecated This was deprecated in HAPI FHIR 4.1.0 as it provides duplicate functionality to the {@link #addRootPropertiesToBundle(String, BundleLinks, Integer, IPrimitiveType)} * and {@link #addResourcesToBundle(List, BundleTypeEnum, String, BundleInclusionRule, Set)} methods */ @Deprecated default void initializeBundleFromResourceList(String theAuthor, List theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) { - addRootPropertiesToBundle(null, null, null, null, null, theResult.size(), theBundleType, null); + addTotalResultsToBundle(theResult.size(), theBundleType); addResourcesToBundle(new ArrayList<>(theResult), theBundleType, null, null, null); } @@ -56,4 +57,5 @@ public interface IVersionSpecificBundleFactory { List toListOfResources(); + void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType); } diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java index 7a9fe404dab..ba22eacfbda 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.cli; import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; @@ -44,7 +45,6 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.io.FileUtils; -import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; import org.hl7.fhir.dstu3.model.Bundle.BundleType; @@ -720,7 +720,7 @@ public class ExampleDataUploader extends BaseCommand { ourLog.info("About to upload {} examples in a transaction, {} remaining", subResourceList.size(), resources.size()); IVersionSpecificBundleFactory bundleFactory = ctx.newBundleFactory(); - bundleFactory.addRootPropertiesToBundle(null, null, null, null, null, subResourceList.size(), BundleTypeEnum.TRANSACTION, null); + bundleFactory.addTotalResultsToBundle(subResourceList.size(), BundleTypeEnum.TRANSACTION); bundleFactory.addResourcesToBundle(new ArrayList<>(subResourceList), BundleTypeEnum.TRANSACTION, null, null, null); IBaseResource subBundle = bundleFactory.getResourceBundle(); diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java index 6f5c3d75bc3..1b0fa3a8b70 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java @@ -1,44 +1,27 @@ package ca.uhn.fhir.rest.client.method; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -/* - * #%L - * HAPI FHIR - Client Framework - * %% - * 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 java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.instance.model.api.*; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; -import ca.uhn.fhir.rest.api.*; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; +import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.client.api.IHttpClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.IBaseBinary; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; /** * @author James Agnew @@ -173,7 +156,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca parser.setOmitResourceId(myOmitResourceId); if (myResources != null) { IVersionSpecificBundleFactory bundleFactory = getContext().newBundleFactory(); - bundleFactory.addRootPropertiesToBundle(null, null, null, null, null, myResources.size(), myBundleType, null); + bundleFactory.addTotalResultsToBundle(myResources.size(), myBundleType); bundleFactory.addResourcesToBundle(myResources, myBundleType, null, null, null); IBaseResource bundleRes = bundleFactory.getResourceBundle(); return parser.encodeResourceToString(bundleRes); diff --git a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/IncludesExamples.java b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/IncludesExamples.java index f03d5ab8f89..bd03458ec1d 100644 --- a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/IncludesExamples.java +++ b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/IncludesExamples.java @@ -44,7 +44,7 @@ public class IncludesExamples { FhirContext ctx = FhirContext.forDstu2(); R4BundleFactory bf = new R4BundleFactory(ctx); - bf.addRootPropertiesToBundle(null, null, null, null, null, resources.size(), BundleTypeEnum.SEARCHSET, null); + bf.addTotalResultsToBundle(resources.size(), BundleTypeEnum.SEARCHSET); bf.addResourcesToBundle(new ArrayList<>(resources), BundleTypeEnum.SEARCHSET, null, null, null); IBaseResource b = bf.getResourceBundle(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java index 309037bd3e5..b05ac8153e4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java @@ -25,13 +25,12 @@ import ca.uhn.fhir.jpa.dao.SearchBuilderFactory; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.BasePagingProvider; -import ca.uhn.fhir.rest.server.IPagingProvider; import org.springframework.beans.factory.annotation.Autowired; // Note: this class is not annotated with @Service because we want to // explicitly define it in BaseConfig.java. This is done so that // implementors can override if they want to. -public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider { +public class DatabaseBackedPagingProvider extends BasePagingProvider { @Autowired private DaoRegistry myDaoRegistry; diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/IRestfulServer.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/IRestfulServer.java index ec1b8de448e..d8420f8e68b 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/IRestfulServer.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/IRestfulServer.java @@ -33,4 +33,7 @@ public interface IRestfulServer extends IRestfulServer PreferReturnEnum getDefaultPreferReturn(); + default boolean canStoreSearchResults() { + return getPagingProvider() != null && getPagingProvider().canStoreSearchResults(); + } } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java index c3c548f511b..e76827f0c45 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java @@ -27,10 +27,10 @@ import org.apache.commons.lang3.Validate; import java.util.LinkedHashMap; import java.util.UUID; -public class FifoMemoryPagingProvider extends BasePagingProvider implements IPagingProvider { +public class FifoMemoryPagingProvider extends BasePagingProvider { - private LinkedHashMap myBundleProviders; - private int mySize; + private final LinkedHashMap myBundleProviders; + private final int mySize; public FifoMemoryPagingProvider(int theSize) { Validate.isTrue(theSize > 0, "theSize must be greater than 0"); diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/IPagingProvider.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/IPagingProvider.java index 5474784c97c..bd3add2e09b 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/IPagingProvider.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/IPagingProvider.java @@ -28,10 +28,23 @@ import javax.annotation.Nullable; public interface IPagingProvider { + /** + * if no _count parameter is provided, use this for the page size + */ int getDefaultPageSize(); + /** + * if the _count parameter is larger than this value, reduce it to this value + */ int getMaximumPageSize(); + /** + * @return true if the paging provider is able to store search results. + */ + default boolean canStoreSearchResults() { + return true; + } + /** * Retrieve a result list by Search ID * diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java index d9ee8fee518..ad808df0047 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java @@ -28,8 +28,8 @@ import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.primitive.InstantDt; -import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.DeleteCascadeModeEnum; import ca.uhn.fhir.rest.api.EncodingEnum; @@ -64,7 +64,19 @@ import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.Writer; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -269,9 +281,9 @@ public class RestfulServerUtils { return b.toString(); } - public static String createOffsetPagingLink(String theServerBase, String requestPath, String tenantId, Integer theOffset, Integer theCount, Map theRequestParameters) { + public static String createOffsetPagingLink(BundleLinks theBundleLinks, String requestPath, String tenantId, Integer theOffset, Integer theCount, Map theRequestParameters) { StringBuilder b = new StringBuilder(); - b.append(theServerBase); + b.append(theBundleLinks.serverBase); if (isNotBlank(requestPath)) { b.append('/'); @@ -304,20 +316,17 @@ public class RestfulServerUtils { return b.toString(); } - public static String createPagingLink(Set theIncludes, RequestDetails theRequestDetails, String theSearchId, int theOffset, int theCount, Map theRequestParameters, boolean thePrettyPrint, - BundleTypeEnum theBundleType) { - return createPagingLink(theIncludes, theRequestDetails, theSearchId, theOffset, theCount, theRequestParameters, thePrettyPrint, - theBundleType, null); + public static String createPagingLink(BundleLinks theBundleLinks, RequestDetails theRequestDetails, String theSearchId, int theOffset, int theCount, Map theRequestParameters) { + return createPagingLink(theBundleLinks, theRequestDetails, theSearchId, theOffset, theCount, theRequestParameters, null); } - public static String createPagingLink(Set theIncludes, RequestDetails theRequestDetails, String theSearchId, String thePageId, Map theRequestParameters, boolean thePrettyPrint, - BundleTypeEnum theBundleType) { - return createPagingLink(theIncludes, theRequestDetails, theSearchId, null, null, theRequestParameters, thePrettyPrint, - theBundleType, thePageId); + public static String createPagingLink(BundleLinks theBundleLinks, RequestDetails theRequestDetails, String theSearchId, String thePageId, Map theRequestParameters) { + return createPagingLink(theBundleLinks, theRequestDetails, theSearchId, null, null, theRequestParameters, + thePageId); } - private static String createPagingLink(Set theIncludes, RequestDetails theRequestDetails, String theSearchId, Integer theOffset, Integer theCount, Map theRequestParameters, boolean thePrettyPrint, - BundleTypeEnum theBundleType, String thePageId) { + private static String createPagingLink(BundleLinks theBundleLinks, RequestDetails theRequestDetails, String theSearchId, Integer theOffset, Integer theCount, Map theRequestParameters, + String thePageId) { String serverBase = theRequestDetails.getFhirServerBase(); @@ -355,15 +364,15 @@ public class RestfulServerUtils { format = replace(format, " ", "+"); b.append(UrlUtil.escapeUrlParam(format)); } - if (thePrettyPrint) { + if (theBundleLinks.prettyPrint) { b.append('&'); b.append(Constants.PARAM_PRETTY); b.append('='); b.append(Constants.PARAM_PRETTY_VALUE_TRUE); } - if (theIncludes != null) { - for (Include nextInclude : theIncludes) { + if (theBundleLinks.getIncludes() != null) { + for (Include nextInclude : theBundleLinks.getIncludes()) { if (isNotBlank(nextInclude.getValue())) { b.append('&'); b.append(Constants.PARAM_INCLUDE); @@ -373,11 +382,11 @@ public class RestfulServerUtils { } } - if (theBundleType != null) { + if (theBundleLinks.bundleType != null) { b.append('&'); b.append(Constants.PARAM_BUNDLETYPE); b.append('='); - b.append(theBundleType.getCode()); + b.append(theBundleLinks.bundleType.getCode()); } // _elements diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java index 9500c20d712..5c37205e17b 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java @@ -7,9 +7,13 @@ import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.Include; -import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.valueset.BundleTypeEnum; -import ca.uhn.fhir.rest.api.*; +import ca.uhn.fhir.rest.api.BundleLinks; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.SummaryEnum; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IRestfulServer; import ca.uhn.fhir.rest.api.server.RequestDetails; @@ -23,7 +27,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.ReflectionUtil; -import ca.uhn.fhir.util.UrlUtil; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -34,7 +37,13 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.Set; import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -124,7 +133,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi List resourceList; Integer numTotalResults = theResult.size(); - if (requestOffset != null || theServer.getPagingProvider() == null) { + if (requestOffset != null || !theServer.canStoreSearchResults()) { if (theLimit != null) { numToReturn = theLimit; } else { @@ -204,31 +213,33 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi } } - String serverBase = theRequest.getFhirServerBase(); - boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); + BundleLinks links = new BundleLinks(theRequest.getFhirServerBase(), theIncludes, RestfulServerUtils.prettyPrintResponse(theServer, theRequest), theBundleType); + links.setSelf(theLinkSelf); - String linkPrev = null; - String linkNext = null; - - if (theServer.getPagingProvider() == null || requestOffset != null) { - int myOffset = requestOffset != null ? requestOffset : 0; + if (requestOffset != null || !theServer.canStoreSearchResults()) { + int offset = requestOffset != null ? requestOffset : 0; // Paging without caching // We're doing requestOffset pages - if (numTotalResults == null || myOffset + numToReturn < numTotalResults) { - linkNext = (RestfulServerUtils.createOffsetPagingLink(serverBase, theRequest.getRequestPath(), theRequest.getTenantId(), myOffset + numToReturn, numToReturn, theRequest.getParameters())); + int requestedToReturn = numToReturn; + if (theServer.getPagingProvider() == null) { + // There is no paging provider at all, so assume we're querying up to all the results we need every time + requestedToReturn += offset; } - if (myOffset > 0) { - int start = Math.max(0, myOffset - numToReturn); - linkPrev = RestfulServerUtils.createOffsetPagingLink(serverBase, theRequest.getRequestPath(), theRequest.getTenantId(), start, numToReturn, theRequest.getParameters()); + if (numTotalResults == null || requestedToReturn < numTotalResults) { + links.setNext(RestfulServerUtils.createOffsetPagingLink(links, theRequest.getRequestPath(), theRequest.getTenantId(), offset + numToReturn, numToReturn, theRequest.getParameters())); + } + if (offset > 0) { + int start = Math.max(0, offset - numToReturn); + links.setPrev(RestfulServerUtils.createOffsetPagingLink(links, theRequest.getRequestPath(), theRequest.getTenantId(), start, numToReturn, theRequest.getParameters())); } } else if (isNotBlank(theResult.getCurrentPageId())) { // We're doing named pages searchId = theResult.getUuid(); if (isNotBlank(theResult.getNextPageId())) { - linkNext = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getNextPageId(), theRequest.getParameters(), prettyPrint, theBundleType); + links.setNext(RestfulServerUtils.createPagingLink(links, theRequest, searchId, theResult.getNextPageId(), theRequest.getParameters())); } if (isNotBlank(theResult.getPreviousPageId())) { - linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getPreviousPageId(), theRequest.getParameters(), prettyPrint, theBundleType); + links.setPrev(RestfulServerUtils.createPagingLink(links, theRequest, searchId, theResult.getPreviousPageId(), theRequest.getParameters())); } } else if (searchId != null) { /* @@ -239,24 +250,17 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi */ if (resourceList.size() > 0) { if (numTotalResults == null || theOffset + numToReturn < numTotalResults) { - linkNext = (RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType)); + links.setNext((RestfulServerUtils.createPagingLink(links, theRequest, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters()))); } if (theOffset > 0) { int start = Math.max(0, theOffset - numToReturn); - linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, start, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType); + links.setPrev(RestfulServerUtils.createPagingLink(links, theRequest, searchId, start, numToReturn, theRequest.getParameters())); } } } - bundleFactory.addRootPropertiesToBundle(theResult.getUuid(), serverBase, theLinkSelf, linkPrev, linkNext, theResult.size(), theBundleType, theResult.getPublished()); - bundleFactory.addResourcesToBundle(new ArrayList<>(resourceList), theBundleType, serverBase, theServer.getBundleInclusionRule(), theIncludes); - - if (theServer.getPagingProvider() != null) { - int limit; - limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize(); - limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize()); - - } + bundleFactory.addRootPropertiesToBundle(theResult.getUuid(), links, theResult.size(), theResult.getPublished()); + bundleFactory.addResourcesToBundle(new ArrayList<>(resourceList), theBundleType, links.serverBase, theServer.getBundleInclusionRule(), theIncludes); return bundleFactory.getResourceBundle(); @@ -280,8 +284,9 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi /* * Figure out the self-link for this request */ - String serverBase = theRequest.getServerBaseForRequest(); - String linkSelf = RestfulServerUtils.createLinkSelf(theRequest.getFhirServerBase(), theRequest); + + BundleLinks bundleLinks = new BundleLinks(theRequest.getServerBaseForRequest(), null, RestfulServerUtils.prettyPrintResponse(theServer, theRequest), getResponseBundleType()); + bundleLinks.setSelf(RestfulServerUtils.createLinkSelf(theRequest.getFhirServerBase(), theRequest)); if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) { IBaseResource resource; @@ -300,7 +305,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi */ IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory(); bundleFactory.initializeWithBundleResource(resource); - bundleFactory.addRootPropertiesToBundle(null, theRequest.getFhirServerBase(), linkSelf, null, null, count, getResponseBundleType(), lastUpdated); + bundleFactory.addRootPropertiesToBundle(null, bundleLinks, count, lastUpdated); responseObject = resource; } else { @@ -327,7 +332,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) && responseEncoding != null ? responseEncoding.getEncoding() : null; - responseObject = createBundleFromBundleProvider(theServer, theRequest, count, linkSelf, includes, result, start, getResponseBundleType(), linkEncoding, null); + responseObject = createBundleFromBundleProvider(theServer, theRequest, count, RestfulServerUtils.createLinkSelf(theRequest.getFhirServerBase(), theRequest), includes, result, start, getResponseBundleType(), linkEncoding, null); } break; } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/PageMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/PageMethodBinding.java index a3fb8c9f671..b0085db59b6 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/PageMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/PageMethodBinding.java @@ -86,7 +86,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { Integer offsetI; int start = 0; - IBundleProvider resultList; + IBundleProvider bundleProvider; String pageId = null; String[] pageIdParams = theRequest.getParameters().get(Constants.PARAM_PAGEID); @@ -101,21 +101,21 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { if (pageId != null) { // This is a page request by Search ID and Page ID - resultList = pagingProvider.retrieveResultList(theRequest, thePagingAction, pageId); - validateHaveBundleProvider(thePagingAction, resultList); + bundleProvider = pagingProvider.retrieveResultList(theRequest, thePagingAction, pageId); + validateHaveBundleProvider(thePagingAction, bundleProvider); } else { // This is a page request by Search ID and Offset - resultList = pagingProvider.retrieveResultList(theRequest, thePagingAction); - validateHaveBundleProvider(thePagingAction, resultList); + bundleProvider = pagingProvider.retrieveResultList(theRequest, thePagingAction); + validateHaveBundleProvider(thePagingAction, bundleProvider); offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET); if (offsetI == null || offsetI < 0) { offsetI = 0; } - Integer totalNum = resultList.size(); + Integer totalNum = bundleProvider.size(); start = offsetI; if (totalNum != null) { start = Math.min(start, totalNum); @@ -155,7 +155,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { count = pagingProvider.getMaximumPageSize(); } - return createBundleFromBundleProvider(theServer, theRequest, count, linkSelf, includes, resultList, start, bundleType, encodingEnum, thePagingAction); + return createBundleFromBundleProvider(theServer, theRequest, count, linkSelf, includes, bundleProvider, start, bundleType, encodingEnum, thePagingAction); } private void validateHaveBundleProvider(String thePagingAction, IBundleProvider theBundleProvider) { diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/Dstu2_1BundleFactory.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/Dstu2_1BundleFactory.java index f41f496de41..886ba80e32d 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/Dstu2_1BundleFactory.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/Dstu2_1BundleFactory.java @@ -25,6 +25,7 @@ import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.util.ResourceReferenceInfo; @@ -35,9 +36,18 @@ import org.hl7.fhir.dstu2016may.model.Bundle.SearchEntryMode; import org.hl7.fhir.dstu2016may.model.DomainResource; import org.hl7.fhir.dstu2016may.model.IdType; import org.hl7.fhir.dstu2016may.model.Resource; -import org.hl7.fhir.instance.model.api.*; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; -import java.util.*; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -147,31 +157,39 @@ public class Dstu2_1BundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); - myBase = theServerBase; + myBase = theBundleLinks.serverBase; if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (myBundle.getIdElement().isEmpty()) { - myBundle.setId(UUID.randomUUID().toString()); - } if (myBundle.getMeta().getLastUpdated() == null && theLastUpdated != null) { myBundle.getMeta().getLastUpdatedElement().setValueAsString(theLastUpdated.getValueAsString()); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); + } + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (myBundle.getIdElement().isEmpty()) { + myBundle.setId(UUID.randomUUID().toString()); } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/Dstu2BundleFactory.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/Dstu2BundleFactory.java index 874e1ed4723..e0f235ac6d5 100644 --- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/Dstu2BundleFactory.java +++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/Dstu2BundleFactory.java @@ -19,25 +19,37 @@ package ca.uhn.fhir.rest.server.provider.dstu2; * limitations under the License. * #L% */ -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.util.*; - -import org.hl7.fhir.instance.model.api.*; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.api.BundleInclusionRule; -import ca.uhn.fhir.model.api.*; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; 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.Link; import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; -import ca.uhn.fhir.model.valueset.*; +import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; +import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum; +import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.util.ResourceReferenceInfo; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; public class Dstu2BundleFactory implements IVersionSpecificBundleFactory { private String myBase; @@ -138,31 +150,39 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); - myBase = theServerBase; + myBase = theBundleLinks.serverBase; if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (myBundle.getId().isEmpty()) { - myBundle.setId(UUID.randomUUID().toString()); - } if (ResourceMetadataKeyEnum.UPDATED.get(myBundle) == null) { ResourceMetadataKeyEnum.UPDATED.put(myBundle, (InstantDt) theLastUpdated); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); + } + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (myBundle.getId().isEmpty()) { + myBundle.setId(UUID.randomUUID().toString()); } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java index 4b2ee5e7200..c7b3015047f 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java @@ -25,6 +25,7 @@ import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; @@ -36,9 +37,18 @@ import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode; import org.hl7.fhir.dstu3.model.DomainResource; import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.Resource; -import org.hl7.fhir.instance.model.api.*; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; -import java.util.*; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -170,31 +180,39 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); - myBase = theServerBase; + myBase = theBundleLinks.serverBase; if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (myBundle.getIdElement().isEmpty()) { - myBundle.setId(UUID.randomUUID().toString()); - } if (myBundle.getMeta().getLastUpdated() == null && theLastUpdated != null) { myBundle.getMeta().getLastUpdatedElement().setValueAsString(theLastUpdated.getValueAsString()); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); + } + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (myBundle.getIdElement().isEmpty()) { + myBundle.setId(UUID.randomUUID().toString()); } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { diff --git a/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2hl7org/Dstu2Hl7OrgBundleFactory.java b/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2hl7org/Dstu2Hl7OrgBundleFactory.java index a1b6075d0c4..80ef96fe2d7 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2hl7org/Dstu2Hl7OrgBundleFactory.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2hl7org/Dstu2Hl7OrgBundleFactory.java @@ -25,6 +25,7 @@ import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; @@ -42,6 +43,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; @@ -183,16 +185,13 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, - Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType theLastUpdated) { + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, + Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (isBlank(myBundle.getId())) { - myBundle.setId(UUID.randomUUID().toString()); - } if (myBundle.getMeta().getLastUpdated() == null && theLastUpdated != null) { InstantType instantType = new InstantType(); @@ -200,17 +199,28 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory { myBundle.getMeta().setLastUpdatedElement(instantType); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); } - myBase = theServerBase; + myBase = theBundleLinks.serverBase; + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (isBlank(myBundle.getId())) { + myBundle.setId(UUID.randomUUID().toString()); + } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { myBundle.getTypeElement().setValueAsString(theBundleType.getCode()); diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java index dfb264d14e3..893bf9e86c3 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java @@ -25,11 +25,15 @@ import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.util.ResourceReferenceInfo; -import org.hl7.fhir.instance.model.api.*; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleLinkComponent; @@ -38,7 +42,13 @@ import org.hl7.fhir.r4.model.DomainResource; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Resource; -import java.util.*; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -172,31 +182,39 @@ public class R4BundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); - myBase = theServerBase; + myBase = theBundleLinks.serverBase; if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (myBundle.getIdElement().isEmpty()) { - myBundle.setId(UUID.randomUUID().toString()); - } if (myBundle.getMeta().getLastUpdated() == null && theLastUpdated != null) { myBundle.getMeta().getLastUpdatedElement().setValueAsString(theLastUpdated.getValueAsString()); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); + } + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (myBundle.getIdElement().isEmpty()) { + myBundle.setId(UUID.randomUUID().toString()); } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingUsingNamedPagesR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingUsingNamedPagesR4Test.java index f78cf651d06..29a88e044e2 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingUsingNamedPagesR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingUsingNamedPagesR4Test.java @@ -59,6 +59,7 @@ public class PagingUsingNamedPagesR4Test { @BeforeEach public void before() { myPagingProvider = mock(IPagingProvider.class); + when(myPagingProvider.canStoreSearchResults()).thenReturn(true); servlet.setPagingProvider(myPagingProvider); ourNextBundleProvider = null; } diff --git a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java index 42a3783f6a7..37d1bd48eb4 100644 --- a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java +++ b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java @@ -25,11 +25,15 @@ import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.BundleLinks; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.util.ResourceReferenceInfo; -import org.hl7.fhir.instance.model.api.*; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.Bundle.BundleLinkComponent; @@ -38,7 +42,13 @@ import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.IdType; import org.hl7.fhir.r5.model.Resource; -import java.util.*; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -172,31 +182,39 @@ public class R5BundleFactory implements IVersionSpecificBundleFactory { } @Override - public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, + public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType theLastUpdated) { ensureBundle(); - myBase = theServerBase; + myBase = theBundleLinks.serverBase; if (myBundle.getIdElement().isEmpty()) { myBundle.setId(theId); } - if (myBundle.getIdElement().isEmpty()) { - myBundle.setId(UUID.randomUUID().toString()); - } if (myBundle.getMeta().getLastUpdated() == null && theLastUpdated != null) { myBundle.getMeta().getLastUpdatedElement().setValueAsString(theLastUpdated.getValueAsString()); } - if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theLinkSelf)) { - myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theLinkSelf); + if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theBundleLinks.getSelf())) { + myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theBundleLinks.getSelf()); } - if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theLinkNext)) { - myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext); + if (!hasLink(Constants.LINK_NEXT, myBundle) && isNotBlank(theBundleLinks.getNext())) { + myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theBundleLinks.getNext()); } - if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) { - myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev); + if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theBundleLinks.getPrev())) { + myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theBundleLinks.getPrev()); + } + + addTotalResultsToBundle(theTotalResults, theBundleLinks.bundleType); + } + + @Override + public void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType) { + ensureBundle(); + + if (myBundle.getIdElement().isEmpty()) { + myBundle.setId(UUID.randomUUID().toString()); } if (myBundle.getTypeElement().isEmpty() && theBundleType != null) { From 5b5023e6ac2885391bb3027a75c2120d246131cc Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Mon, 11 Jan 2021 21:00:12 -0500 Subject: [PATCH 3/4] License headers --- .../ca/uhn/fhir/rest/api/BundleLinks.java | 20 +++++++++++++++++++ .../BaseHttpClientInvocationWithContents.java | 20 +++++++++++++++++++ .../entity/NormalizedQuantitySearchLevel.java | 20 +++++++++++++++++++ .../ResourceIndexedSearchParamQuantity.java | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java index c482e15f7d9..229c37a0f79 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/BundleLinks.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.rest.api; +/*- + * #%L + * HAPI FHIR - Core Library + * %% + * 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.model.api.Include; import ca.uhn.fhir.model.valueset.BundleTypeEnum; diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java index 1b0fa3a8b70..586bfdcb0ff 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseHttpClientInvocationWithContents.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.rest.client.method; +/*- + * #%L + * HAPI FHIR - Client Framework + * %% + * 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.context.FhirVersionEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum; diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NormalizedQuantitySearchLevel.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NormalizedQuantitySearchLevel.java index 764a8c26d78..f7c819b5a92 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NormalizedQuantitySearchLevel.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NormalizedQuantitySearchLevel.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.model.entity; +/*- + * #%L + * HAPI FHIR Model + * %% + * 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% + */ + /** * Support different UCUM services level for FHIR Quantity data type. * diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java index d435650cda0..75e99a94150 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java @@ -197,4 +197,4 @@ public class ResourceIndexedSearchParamQuantity extends ResourceIndexedSearchPar return retval; } -} \ No newline at end of file +} From ef407d85bfd4eb8942bc922310339a012fed35cb Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Tue, 12 Jan 2021 08:55:12 -0500 Subject: [PATCH 4/4] Add logging --- .../RepositoryValidatingInterceptor.java | 35 ++++++++++++++----- .../validation/RequireValidationRule.java | 19 +++++++--- .../validation/RuleDisallowProfile.java | 12 +++++++ .../RuleRequireProfileDeclaration.java | 11 ++++++ .../ca/uhn/fhir/jpa/packages/NpmR4Test.java | 6 +++- pom.xml | 2 +- 6 files changed, 71 insertions(+), 14 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RepositoryValidatingInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RepositoryValidatingInterceptor.java index 6072694ea68..fc503f65d3c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RepositoryValidatingInterceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RepositoryValidatingInterceptor.java @@ -24,21 +24,19 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.interceptor.api.Hook; import ca.uhn.fhir.interceptor.api.Interceptor; import ca.uhn.fhir.interceptor.api.Pointcut; -import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.util.OperationOutcomeUtil; import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; -import org.apache.commons.collections4.MultiMap; -import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.lang3.Validate; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; import java.util.Collection; -import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * This interceptor enforces validation rules on any data saved in a HAPI FHIR JPA repository. @@ -48,12 +46,13 @@ import java.util.List; @Interceptor public class RepositoryValidatingInterceptor { + private static final Logger ourLog = LoggerFactory.getLogger(RepositoryValidatingInterceptor.class); private Multimap myRules = ArrayListMultimap.create(); private FhirContext myFhirContext; /** * Constructor - * + *

* If this constructor is used, {@link #setFhirContext(FhirContext)} and {@link #setRules(List)} must be called * manually before the interceptor is used. */ @@ -65,7 +64,7 @@ public class RepositoryValidatingInterceptor { * Constructor * * @param theFhirContext The FHIR Context (must not be null) - * @param theRules The rule list (must not be null) + * @param theRules The rule list (must not be null) */ public RepositoryValidatingInterceptor(FhirContext theFhirContext, List theRules) { setFhirContext(theFhirContext); @@ -88,6 +87,26 @@ public class RepositoryValidatingInterceptor { for (IRepositoryValidatingRule next : theRules) { myRules.put(next.getResourceType(), next); } + + String rulesDescription = "RepositoryValidatingInterceptor has rules:\n" + describeRules(); + ourLog.info(rulesDescription); + + } + + /** + * Returns a multiline string describing the rules in place for this interceptor. + * This is mostly intended for troubleshooting, and the format returned is only + * semi-human-consumable. + */ + @Nonnull + public String describeRules() { + return " * " + myRules + .values() + .stream() + .distinct() + .map(t -> t.toString()) + .sorted() + .collect(Collectors.joining("\n * ")); } /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RequireValidationRule.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RequireValidationRule.java index be558934b81..f682f1c9590 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RequireValidationRule.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RequireValidationRule.java @@ -28,6 +28,8 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; import ca.uhn.fhir.validation.SingleValidationMessage; import ca.uhn.fhir.validation.ValidationResult; import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r5.utils.IResourceValidator; @@ -38,16 +40,12 @@ import java.util.Collections; import java.util.List; class RequireValidationRule extends BaseTypedRule { - private final IValidationSupport myValidationSupport; - private final ValidatorResourceFetcher myValidatorResourceFetcher; private final FhirInstanceValidator myValidator; private ResultSeverityEnum myRejectOnSeverity = ResultSeverityEnum.ERROR; private List myTagOnSeverity = Collections.emptyList(); public RequireValidationRule(FhirContext theFhirContext, String theType, IValidationSupport theValidationSupport, ValidatorResourceFetcher theValidatorResourceFetcher) { super(theFhirContext, theType); - myValidationSupport = theValidationSupport; - myValidatorResourceFetcher = theValidatorResourceFetcher; myValidator = new FhirInstanceValidator(theValidationSupport); myValidator.setValidatorResourceFetcher(theValidatorResourceFetcher); @@ -129,6 +127,19 @@ class RequireValidationRule extends BaseTypedRule { public String getTagCode() { return myTagCode; } + + @Override + public String toString() { + return ResultSeverityEnum.values()[mySeverity].name() + "/" + myTagSystem + "/" + myTagCode; + } } + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("resourceType", getResourceType()) + .append("rejectOnSeverity", myRejectOnSeverity) + .append("tagOnSeverity", myTagOnSeverity) + .toString(); + } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleDisallowProfile.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleDisallowProfile.java index e667deb8b33..f6f499770ef 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleDisallowProfile.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleDisallowProfile.java @@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.interceptor.validation; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.util.UrlUtil; import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; @@ -57,4 +59,14 @@ class RuleDisallowProfile extends BaseTypedRule { return RuleEvaluation.forSuccess(this); } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("resourceType", getResourceType()) + .append("profiles", myProfileUrls) + .toString(); + } + + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleRequireProfileDeclaration.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleRequireProfileDeclaration.java index 3b0a2527fe9..8688a19e668 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleRequireProfileDeclaration.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/validation/RuleRequireProfileDeclaration.java @@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.interceptor.validation; */ import ca.uhn.fhir.context.FhirContext; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.hl7.fhir.instance.model.api.IBaseResource; import javax.annotation.Nonnull; @@ -53,4 +55,13 @@ class RuleRequireProfileDeclaration extends BaseTypedRule { } + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("resourceType", getResourceType()) + .append("profiles", myProfileOptions) + .toString(); + } + + } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java index 2e8b6944700..3b3efcb1aef 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java @@ -130,7 +130,11 @@ public class NpmR4Test extends BaseJpaR4Test { jpaPackageCache.getPackageServers().clear(); jpaPackageCache.addPackageServer("https://packages.fhir.org"); - PackageInstallationSpec spec = new PackageInstallationSpec().setName("hl7.fhir.us.core").setVersion("3.1.0").setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(true); + PackageInstallationSpec spec = new PackageInstallationSpec() + .setName("hl7.fhir.us.core") + .setVersion("3.1.0") + .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL) + .setFetchDependencies(true); igInstaller.install(spec); runInTransaction(()->{ diff --git a/pom.xml b/pom.xml index 02952218069..d94a6d732f6 100644 --- a/pom.xml +++ b/pom.xml @@ -1240,7 +1240,7 @@ org.awaitility awaitility - 4.0.1 + 4.0.3 org.codehaus.plexus