Correct bugs reported by LGTM (#1533)

* Correct bugs reported by LGTM

* Add some tests

* A few more updates

* YAML update

* Test fixes

* One more test fix

* Test fix
This commit is contained in:
James Agnew 2019-10-09 19:26:57 -05:00 committed by GitHub
parent eb0a657b62
commit e656863a73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 191 additions and 273 deletions

View File

@ -821,7 +821,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
byte[] resourceBytes;
ResourceEncodingEnum resourceEncoding;
Collection<? extends BaseTag> myTagList;
Long version;
long version;
String provenanceSourceUri = null;
String provenanceRequestId = null;

View File

@ -55,8 +55,6 @@ import ca.uhn.fhir.validation.*;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.InstantType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.transaction.PlatformTransactionManager;
@ -193,9 +191,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
public DaoMethodOutcome delete(IIdType theId, DeleteConflictList theDeleteConflicts, RequestDetails theRequest) {
if (theId == null || !theId.hasIdPart()) {
throw new InvalidRequestException("Can not perform delete, no ID provided");
}
validateIdPresentForDelete(theId);
final ResourceTable entity = readEntityLatestVersion(theId, theRequest);
if (theId.hasVersionIdPart() && Long.parseLong(theId.getVersionIdPart()) != entity.getVersion()) {
throw new ResourceVersionConflictException("Trying to delete " + theId + " but this is not the current version");
@ -271,8 +268,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
public DaoMethodOutcome delete(IIdType theId, RequestDetails theRequestDetails) {
validateIdPresentForDelete(theId);
DeleteConflictList deleteConflicts = new DeleteConflictList();
if (theId != null && isNotBlank(theId.getValue())) {
if (isNotBlank(theId.getValue())) {
deleteConflicts.setResourceIdMarkedForDeletion(theId);
}
@ -376,6 +375,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return outcome;
}
private void validateIdPresentForDelete(IIdType theId) {
if (theId == null || !theId.hasIdPart()) {
throw new InvalidRequestException("Can not perform delete, no ID provided");
}
}
@PostConstruct
public void detectSearchDaoDisabled() {
if (mySearchDao != null && mySearchDao.isDisabled()) {
@ -559,7 +564,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
throw new MethodNotAllowedException("$expunge is not enabled on this server");
}
}
@Override
@Transactional(propagation = Propagation.NEVER)
public ExpungeOutcome expunge(IIdType theId, ExpungeOptions theExpungeOptions, RequestDetails theRequest) {
@ -573,9 +578,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager);
BaseHasResource entity = txTemplate.execute(t -> readEntity(theId, theRequest));
Validate.notNull(entity, "Resource with ID %s not found in database", theId);
if (theId.hasVersionIdPart()) {
BaseHasResource currentVersion;
currentVersion = txTemplate.execute(t -> readEntity(theId.toVersionless(), theRequest));
Validate.notNull(currentVersion, "Current version of resource with ID %s not found in database", theId.toVersionless());
if (entity.getVersion() == currentVersion.getVersion()) {
throw new PreconditionFailedException("Can not perform version-specific expunge of resource " + theId.toUnqualified().getValue() + " as this is the current version");
}
@ -1500,11 +1509,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
} else if (isNotBlank(theRawResource)) {
result = validator.validateWithResult(theRawResource, options);
} else if (theResource != null) {
result = validator.validateWithResult(theResource, options);
} else {
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "cantValidateWithNoResource");
throw new InvalidRequestException(msg);
result = validator.validateWithResult(theResource, options);
}
if (result.isSuccessful()) {
@ -1519,9 +1525,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
/**
* Get the resource definition from the criteria which specifies the resource type
*
* @param criteria
* @return
*/
@Override
public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(String criteria) {

View File

@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl.SearchTask;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -110,7 +111,8 @@ public class PersistedJpaSearchFirstPageBundleProvider extends PersistedJpaBundl
if (theResource instanceof IAnyResource) {
return "include".equals(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(((IAnyResource) theResource)));
}
return "include".equals(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(((IResource) theResource)));
BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(((IResource) theResource));
return BundleEntrySearchModeEnum.INCLUDE.equals(searchMode);
}
@Override

View File

@ -102,6 +102,7 @@ public class SubscriptionActivatingInterceptor {
.getValueAsString();
Subscription.SubscriptionChannelType subscriptionChannelType = Subscription.SubscriptionChannelType.fromCode(subscriptionChannelTypeCode);
// Only activate supported subscriptions
if (!myDaoConfig.getSupportedSubscriptionTypes().contains(subscriptionChannelType)) {
return false;

View File

@ -606,6 +606,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.returnBundle(Bundle.class)
.execute();
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res));
assertEquals(3, res.getEntry().size());
assertEquals(1, BundleUtil.toListOfResourcesOfType(myFhirCtx, res, Encounter.class).size());
assertEquals(e1id.toUnqualifiedVersionless(), BundleUtil.toListOfResourcesOfType(myFhirCtx, res, Encounter.class).get(0).getIdElement().toUnqualifiedVersionless());

View File

@ -17,6 +17,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.After;
import org.junit.AfterClass;
@ -183,7 +184,9 @@ public class SearchCoordinatorSvcImplTest {
when(mySearchResultCacheSvc.fetchAllResultPids(any())).thenReturn(allResults);
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any())).thenAnswer(t->{
Search search = t.getArgument(0, Search.class);
Object argument = t.getArgument(0);
Validate.isTrue( argument instanceof Search, "Argument is " + argument);
Search search = (Search) argument;
assertEquals(SearchStatusEnum.PASSCMPLET, search.getStatus());
search.setStatus(SearchStatusEnum.LOADING);
return Optional.of(search);

View File

@ -3,11 +3,13 @@ package ca.uhn.fhir.jpa.subscription.resthook;
import ca.uhn.fhir.jpa.config.StoppableSubscriptionDeliveringRestHookSubscriber;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.subscription.BaseSubscriptionsR4Test;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*;
import org.junit.After;
import org.junit.Assert;
@ -16,6 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -870,6 +873,28 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test {
assertEquals(1, subscriptionCount());
}
/**
* Make sure we don't activate a subscription if its type is incorrect
*/
@Test
public void testSubscriptionDoesntActivateIfRestHookIsNotEnabled() throws InterruptedException {
Set<org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType> existingSupportedSubscriptionTypes = myDaoConfig.getSupportedSubscriptionTypes();
myDaoConfig.clearSupportedSubscriptionTypesForUnitTest();
try {
Subscription subscription = newSubscription("Observation?", "application/fhir+json");
IIdType id = ourClient.create().resource(subscription).execute().getId().toUnqualifiedVersionless();
Thread.sleep(1000);
subscription = ourClient.read().resource(Subscription.class).withId(id).execute();
assertEquals(Subscription.SubscriptionStatus.REQUESTED, subscription.getStatus());
} finally {
existingSupportedSubscriptionTypes.forEach(t-> myDaoConfig.addSupportedSubscriptionType(t));
}
}
private int subscriptionCount() {
IBaseBundle found = ourClient.search().forResource(Subscription.class).cacheControl(new CacheControlDirective().setNoCache(true)).execute();
return toUnqualifiedVersionlessIdValues(found).size();

View File

@ -127,16 +127,18 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
return myLatitude;
}
public void setLatitude(double theLatitude) {
public ResourceIndexedSearchParamCoords setLatitude(double theLatitude) {
myLatitude = theLatitude;
return this;
}
public double getLongitude() {
return myLongitude;
}
public void setLongitude(double theLongitude) {
public ResourceIndexedSearchParamCoords setLongitude(double theLongitude) {
myLongitude = theLongitude;
return this;
}
@Override

View File

@ -151,16 +151,18 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
return myValueHigh;
}
public void setValueHigh(Date theValueHigh) {
public ResourceIndexedSearchParamDate setValueHigh(Date theValueHigh) {
myValueHigh = theValueHigh;
return this;
}
public Date getValueLow() {
return myValueLow;
}
public void setValueLow(Date theValueLow) {
public ResourceIndexedSearchParamDate setValueLow(Date theValueLow) {
myValueLow = theValueLow;
return this;
}
@Override

View File

@ -202,9 +202,10 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
return myValue;
}
public void setValue(BigDecimal theValue) {
public ResourceIndexedSearchParamQuantity setValue(BigDecimal theValue) {
clearHashes();
myValue = theValue;
return this;
}
@Override

View File

@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.model.entity;
import ca.uhn.fhir.jpa.model.util.StringNormalizer;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.param.StringParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -243,22 +242,24 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
return myValueExact;
}
public void setValueExact(String theValueExact) {
public ResourceIndexedSearchParamString setValueExact(String theValueExact) {
if (defaultString(theValueExact).length() > MAX_LENGTH) {
throw new IllegalArgumentException("Value is too long: " + theValueExact.length());
}
myValueExact = theValueExact;
return this;
}
public String getValueNormalized() {
return myValueNormalized;
}
public void setValueNormalized(String theValueNormalized) {
public ResourceIndexedSearchParamString setValueNormalized(String theValueNormalized) {
if (defaultString(theValueNormalized).length() > MAX_LENGTH) {
throw new IllegalArgumentException("Value is too long: " + theValueNormalized.length());
}
myValueNormalized = theValueNormalized;
return this;
}
@Override

View File

@ -214,9 +214,10 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
return myValue;
}
public void setValue(String theValue) {
public ResourceIndexedSearchParamToken setValue(String theValue) {
clearHashes();
myValue = StringUtils.defaultIfBlank(theValue, null);
return this;
}
@Override

View File

@ -156,8 +156,9 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
return myUri;
}
public void setUri(String theUri) {
public ResourceIndexedSearchParamUri setUri(String theUri) {
myUri = StringUtils.defaultIfBlank(theUri, null);
return this;
}
@Override

View File

@ -0,0 +1,25 @@
package ca.uhn.fhir.jpa.model.entity;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class ResourceIndexedSearchParamCoordsTest {
@Test
public void testEquals() {
ResourceIndexedSearchParamCoords val1 = new ResourceIndexedSearchParamCoords()
.setLatitude(100)
.setLongitude(10);
val1.calculateHashes();
ResourceIndexedSearchParamCoords val2 = new ResourceIndexedSearchParamCoords()
.setLatitude(100)
.setLongitude(10);
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -114,4 +114,21 @@ public class ResourceIndexedSearchParamDateTest {
assertFalse(param2.equals(param));
assertNotEquals(param.hashCode(), param2.hashCode());
}
@Test
public void testEquals() {
ResourceIndexedSearchParamDate val1 = new ResourceIndexedSearchParamDate()
.setValueHigh(new Date(100000000L))
.setValueLow(new Date(111111111L));
val1.calculateHashes();
ResourceIndexedSearchParamDate val2 = new ResourceIndexedSearchParamDate()
.setValueHigh(new Date(100000000L))
.setValueLow(new Date(111111111L));
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -5,6 +5,7 @@ import org.junit.Test;
import java.math.BigDecimal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class ResourceIndexedSearchParamQuantityTest {
@ -24,4 +25,19 @@ public class ResourceIndexedSearchParamQuantityTest {
}
@Test
public void testEquals() {
ResourceIndexedSearchParamQuantity val1 = new ResourceIndexedSearchParamQuantity()
.setValue(new BigDecimal(123));
val1.calculateHashes();
ResourceIndexedSearchParamQuantity val2 = new ResourceIndexedSearchParamQuantity()
.setValue(new BigDecimal(123));
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.model.entity;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@SuppressWarnings("SpellCheckingInspection")
public class ResourceIndexedSearchParamStringTest {
@ -29,4 +30,21 @@ public class ResourceIndexedSearchParamStringTest {
assertEquals(7045214018927566109L, token.getHashExact().longValue());
}
@Test
public void testEquals() {
ResourceIndexedSearchParamString val1 = new ResourceIndexedSearchParamString()
.setValueExact("aaa")
.setValueNormalized("AAA");
val1.calculateHashes();
ResourceIndexedSearchParamString val2 = new ResourceIndexedSearchParamString()
.setValueExact("aaa")
.setValueNormalized("AAA");
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.model.entity;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class ResourceIndexedSearchParamTokenTest {
@ -28,4 +29,18 @@ public class ResourceIndexedSearchParamTokenTest {
assertEquals(-1970227166134682431L, token.getHashValue().longValue());
}
@Test
public void testEquals() {
ResourceIndexedSearchParamToken val1 = new ResourceIndexedSearchParamToken()
.setValue("AAA");
val1.calculateHashes();
ResourceIndexedSearchParamToken val2 = new ResourceIndexedSearchParamToken()
.setValue("AAA");
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -1,10 +1,9 @@
package ca.uhn.fhir.jpa.model.entity;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class ResourceIndexedSearchParamUriTest {
@ -17,5 +16,19 @@ public class ResourceIndexedSearchParamUriTest {
assertEquals(-6132951326739875838L, token.getHashUri().longValue());
}
@Test
public void testEquals() {
ResourceIndexedSearchParamUri val1 = new ResourceIndexedSearchParamUri()
.setUri("http://foo");
val1.calculateHashes();
ResourceIndexedSearchParamUri val2 = new ResourceIndexedSearchParamUri()
.setUri("http://foo");
val2.calculateHashes();
assertEquals(val1, val1);
assertEquals(val1, val2);
assertNotEquals(val1, null);
assertNotEquals(val1, "");
}
}

View File

@ -1761,7 +1761,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
}
theResponse.setContentType("text/plain");
theResponse.setCharacterEncoding("UTF-8");
theResponse.getWriter().write(theException.getMessage());
String message = UrlUtil.sanitizeUrlPart(theException.getMessage());
theResponse.getWriter().write(message);
}
/**

View File

@ -79,7 +79,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
switch (getRestOperationType()) {
case CREATE:
validateResponseNotNullIfItShouldntBe(response);
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
if (response == null || response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
return Constants.STATUS_HTTP_201_CREATED;
}
return Constants.STATUS_HTTP_200_OK;

View File

@ -137,13 +137,15 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
switch (theBundleType) {
case BATCH_RESPONSE:
case TRANSACTION_RESPONSE:
if ("1".equals(id.getVersionIdPart())) {
entry.getResponse().setStatus("201 Created");
} else if (isNotBlank(id.getVersionIdPart())) {
entry.getResponse().setStatus("200 OK");
}
if (isNotBlank(id.getVersionIdPart())) {
entry.getResponse().setEtag(RestfulServerUtils.createEtag(id.getVersionIdPart()));
if (id != null) {
if ("1".equals(id.getVersionIdPart())) {
entry.getResponse().setStatus("201 Created");
} else if (isNotBlank(id.getVersionIdPart())) {
entry.getResponse().setStatus("200 OK");
}
if (isNotBlank(id.getVersionIdPart())) {
entry.getResponse().setEtag(RestfulServerUtils.createEtag(id.getVersionIdPart()));
}
}
break;
}

View File

@ -107,7 +107,7 @@ public class FhirDstu2 implements IFhirVersion {
@Override
public IVersionSpecificBundleFactory newBundleFactory(FhirContext theContext) {
return new Dstu2BundleFactory(theContext);
throw new UnsupportedOperationException();
}
@Override

View File

@ -1,234 +0,0 @@
package ca.uhn.fhir.rest.server.provider.dstu2;
/*
* #%L
* HAPI FHIR Structures - DSTU2 (FHIR v1.0.0)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.api.BundleInclusionRule;
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.base.composite.BaseResourceReferenceDt;
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.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
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.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
private Bundle myBundle;
private FhirContext myContext;
private String myBase;
public Dstu2BundleFactory(FhirContext theContext) {
myContext = theContext;
}
@Override
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
addedResourceIds.add((IdDt) next.getIdElement());
}
}
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource) nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
do {
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
for (ResourceReferenceInfo nextRefInfo : references) {
if (!theBundleInclusionRule.shouldIncludeReferencedResource(nextRefInfo, theIncludes))
continue;
IResource nextRes = (IResource) nextRefInfo.getResourceReference().getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdDt id = nextRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
}
}
}
}
includedResources.addAll(addedResourcesThisPass);
// Linked resources may themselves have linked resources
references = new ArrayList<ResourceReferenceInfo>();
for (IResource iResource : addedResourcesThisPass) {
List<ResourceReferenceInfo> newReferences = myContext.newTerser().getAllResourceReferences(iResource);
references.addAll(newReferences);
}
} while (references.isEmpty() == false);
Entry entry = myBundle.addEntry().setResource(next);
BundleEntryTransactionMethodEnum httpVerb = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(next);
if (httpVerb != null) {
entry.getRequest().getMethodElement().setValueAsString(httpVerb.getCode());
}
populateBundleEntryFullUrl(next, entry);
BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next);
if (searchMode != null) {
entry.getSearch().getModeElement().setValue(searchMode.getCode());
}
}
/*
* Actually add the resources to the bundle
*/
for (IResource next : includedResources) {
Entry entry = myBundle.addEntry();
entry.setResource(next).getSearch().setMode(SearchEntryModeEnum.INCLUDE);
populateBundleEntryFullUrl(next, entry);
}
}
private void populateBundleEntryFullUrl(IResource next, Entry entry) {
if (next.getId().hasBaseUrl()) {
entry.setFullUrl(next.getId().toVersionless().getValue());
} else {
if (isNotBlank(myBase) && next.getId().hasIdPart()) {
IdDt id = next.getId().toVersionless();
id = id.withServerBase(myBase, myContext.getResourceDefinition(next).getName());
entry.setFullUrl(id.getValue());
}
}
}
@Override
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
myBase = theServerBase;
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_NEXT, myBundle) && isNotBlank(theLinkNext)) {
myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(theLinkNext);
}
if (!hasLink(Constants.LINK_PREVIOUS, myBundle) && isNotBlank(theLinkPrev)) {
myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(theLinkPrev);
}
if (myBundle.getTypeElement().isEmpty() && theBundleType != null) {
myBundle.getTypeElement().setValueAsString(theBundleType.getCode());
}
if (myBundle.getTotalElement().isEmpty() && theTotalResults != null) {
myBundle.getTotalElement().setValue(theTotalResults);
}
}
@Override
public IResource getResourceBundle() {
return myBundle;
}
private boolean hasLink(String theLinkType, Bundle theBundle) {
for (Link next : theBundle.getLink()) {
if (theLinkType.equals(next.getRelation())) {
return true;
}
}
return false;
}
@Override
public void initializeWithBundleResource(IBaseResource theBundle) {
myBundle = (Bundle) theBundle;
}
@Override
public List<IBaseResource> toListOfResources() {
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (Entry next : myBundle.getEntry()) {
if (next.getResource() != null) {
retVal.add(next.getResource());
} else if (next.getResponse().getLocationElement().isEmpty() == false) {
IdDt id = new IdDt(next.getResponse().getLocation());
String resourceType = id.getResourceType();
if (isNotBlank(resourceType)) {
IResource res = (IResource) myContext.getResourceDefinition(resourceType).newInstance();
res.setId(id);
retVal.add(res);
}
}
}
return retVal;
}
}

View File

@ -6,3 +6,4 @@ extraction:
- exclude: "**/bootstrap*.js"
- exclude: "**/webapp/fa/*.js"