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
This commit is contained in:
Ken Stevens 2021-01-11 20:42:41 -05:00 committed by GitHub
parent ee7b19fe3c
commit 520400d6ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 370 additions and 185 deletions

View File

@ -116,6 +116,12 @@
<optional>true</optional>
</dependency>
<!-- @Nonnull annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>

View File

@ -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<Include> includes;
private String self;
private String next;
private String prev;
public BundleLinks(String theServerBase, Set<Include> 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<Include> getIncludes() {
if (includes == null) {
return null;
}
return Collections.unmodifiableList(includes);
}
}

View File

@ -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<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes);
void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated);
void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks, Integer theTotalResults, IPrimitiveType<Date> 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<Date>)}
* and {@link #addResourcesToBundle(List, BundleTypeEnum, String, BundleInclusionRule, Set)} methods
*/
@Deprecated
default void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> 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<IBaseResource> toListOfResources();
void addTotalResultsToBundle(Integer theTotalResults, BundleTypeEnum theBundleType);
}

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -33,4 +33,7 @@ public interface IRestfulServer<T extends RequestDetails> extends IRestfulServer
PreferReturnEnum getDefaultPreferReturn();
default boolean canStoreSearchResults() {
return getPagingProvider() != null && getPagingProvider().canStoreSearchResults();
}
}

View File

@ -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<String, IBundleProvider> myBundleProviders;
private int mySize;
private final LinkedHashMap<String, IBundleProvider> myBundleProviders;
private final int mySize;
public FifoMemoryPagingProvider(int theSize) {
Validate.isTrue(theSize > 0, "theSize must be greater than 0");

View File

@ -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
*

View File

@ -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<String, String[]> theRequestParameters) {
public static String createOffsetPagingLink(BundleLinks theBundleLinks, String requestPath, String tenantId, Integer theOffset, Integer theCount, Map<String, String[]> 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<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, int theOffset, int theCount, Map<String, String[]> 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<String, String[]> theRequestParameters) {
return createPagingLink(theBundleLinks, theRequestDetails, theSearchId, theOffset, theCount, theRequestParameters, null);
}
public static String createPagingLink(Set<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, String thePageId, Map<String, String[]> 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<String, String[]> theRequestParameters) {
return createPagingLink(theBundleLinks, theRequestDetails, theSearchId, null, null, theRequestParameters,
thePageId);
}
private static String createPagingLink(Set<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, Integer theOffset, Integer theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
BundleTypeEnum theBundleType, String thePageId) {
private static String createPagingLink(BundleLinks theBundleLinks, RequestDetails theRequestDetails, String theSearchId, Integer theOffset, Integer theCount, Map<String, String[]> 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

View File

@ -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<IBaseResource> 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;
}

View File

@ -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) {

View File

@ -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<Date> 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) {

View File

@ -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<Date> 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) {

View File

@ -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<Date> 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) {

View File

@ -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<Date> theLastUpdated) {
public void addRootPropertiesToBundle(String theId, @Nonnull BundleLinks theBundleLinks,
Integer theTotalResults, IPrimitiveType<Date> 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());

View File

@ -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<Date> 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) {

View File

@ -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;
}

View File

@ -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<Date> 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) {