Merge remote-tracking branch 'remotes/origin/master' into ks-flyway

This commit is contained in:
Ken Stevens 2019-11-04 08:17:30 -05:00
commit d9700b8834
9 changed files with 76 additions and 90 deletions

View File

@ -13,6 +13,8 @@ import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import javax.annotation.Nonnull;
/*
* #%L
* HAPI FHIR - Core Library
@ -117,7 +119,7 @@ public class RuntimeSearchParam {
if (theTargets != null && theTargets.isEmpty() == false) {
myTargets = Collections.unmodifiableSet(theTargets);
} else {
myTargets = null;
myTargets = Collections.emptySet();
}
if (theBase == null || theBase.isEmpty()) {
@ -138,10 +140,15 @@ public class RuntimeSearchParam {
return myBase;
}
@Nonnull
public Set<String> getTargets() {
return myTargets;
}
public boolean hasTargets() {
return !myTargets.isEmpty();
}
public RuntimeSearchParamStatusEnum getStatus() {
return myStatus;
}
@ -176,7 +183,7 @@ public class RuntimeSearchParam {
return Collections.singletonList(path);
}
List<String> retVal = new ArrayList<String>();
List<String> retVal = new ArrayList<>();
StringTokenizer tok = new StringTokenizer(path, "|");
while (tok.hasMoreElements()) {
String nextPath = tok.nextToken().trim();
@ -192,6 +199,7 @@ public class RuntimeSearchParam {
return myProvidesMembershipInCompartments;
}
public enum RuntimeSearchParamStatusEnum {
ACTIVE,
DRAFT,

View File

@ -579,9 +579,8 @@ public class SearchBuilder implements ISearchBuilder {
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
resourceTypes = new ArrayList<>();
Set<String> targetTypes = param.getTargets();
if (targetTypes != null && !targetTypes.isEmpty()) {
if (param.hasTargets()) {
Set<String> targetTypes = param.getTargets();
for (String next : targetTypes) {
resourceTypes.add(myContext.getResourceDefinition(next).getImplementingClass());
}
@ -2494,7 +2493,7 @@ public class SearchBuilder implements ISearchBuilder {
for (String nextPath : paths) {
String sql;
boolean haveTargetTypesDefinedByParam = param.getTargets() != null && param.getTargets().isEmpty() == false;
boolean haveTargetTypesDefinedByParam = param.hasTargets();
if (targetResourceType != null) {
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType = :target_resource_type";
} else if (haveTargetTypesDefinedByParam) {

View File

@ -100,7 +100,7 @@ public class DaoResourceLinkResolver implements IResourceLinkResolver {
throw new InvalidRequestException("Resource " + resName + "/" + theId + " is deleted, specified in path: " + theNextPathsUnsplit);
}
if (theNextSpDef.getTargets() != null && !theNextSpDef.getTargets().contains(theTypeString)) {
if (!theNextSpDef.hasTargets() && theNextSpDef.getTargets().contains(theTypeString)) {
return null;
}
return target;

View File

@ -484,20 +484,6 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testCreateWithInvalidReferenceNoId() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("Organization/");
try {
myPatientDao.create(p, mySrd);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource ID"));
}
}
@Test
public void testCreateWithReferenceBadType() {
Patient p = new Patient();

View File

@ -756,19 +756,6 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
}
@Test
public void testCreateWithInvalidReferenceNoId() {
Patient p = new Patient();
p.addName().setFamily("Hello");
p.getManagingOrganization().setReference("Organization/");
try {
myPatientDao.create(p, mySrd);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource ID"));
}
}
@Test
public void testCreateWithReferenceBadType() {

View File

@ -18,27 +18,6 @@ public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Te
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3BundleTest.class);
/**
* See #401
*/
@Test
public void testBundlePreservesFullUrl() {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
IIdType id = ourClient.create().resource(bundle).execute().getId();
Bundle retBundle = ourClient.read().resource(Bundle.class).withId(id).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
}
@Test
public void testProcessMessage() {

View File

@ -8,6 +8,7 @@ import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Composition;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.Patient;
import org.junit.AfterClass;
import org.junit.Test;
@ -25,11 +26,11 @@ public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
public void testBundlePreservesFullUrl() {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
bundle.setType(BundleType.COLLECTION);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
Patient composition = new Patient();
composition.setActive(true);
bundle.addEntry().setFullUrl("http://foo/").setResource(composition);
IIdType id = ourClient.create().resource(bundle).execute().getId();
@ -37,7 +38,7 @@ public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
assertEquals("http://foo/", bundle.getEntry().get(0).getFullUrl());
}
@Test

View File

@ -400,6 +400,13 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
for (String nextPath : nextPathsSplit) {
List<? extends IBase> allValues;
// This path is hard to parse and isn't likely to produce anything useful anyway
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
if (nextPath.equals("Bundle.entry.resource(0)")) {
continue;
}
}
nextPath = trim(nextPath);
IValueExtractor allValuesFunc = getPathValueExtractor(theResource, nextPath);
try {

View File

@ -39,9 +39,12 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -100,8 +103,8 @@ public class ResourceLinkExtractor {
}
}
private void extractResourceLinks(ResourceIndexedSearchParams theParams, ResourceTable theEntity, Date theUpdateTime, IResourceLinkResolver theResourceLinkResolver, String theResourceType, RuntimeSearchParam nextSpDef, String theNextPathsUnsplit, boolean theMultiType, PathAndRef nextPathAndRef, boolean theFailOnInvalidReference, RequestDetails theRequest) {
Object nextObject = nextPathAndRef.getRef();
private void extractResourceLinks(ResourceIndexedSearchParams theParams, ResourceTable theEntity, Date theUpdateTime, IResourceLinkResolver theResourceLinkResolver, String theResourceType, RuntimeSearchParam theRuntimeSearchParam, String thePath, boolean theMultiType, PathAndRef thePathAndRef, boolean theFailOnInvalidReference, RequestDetails theRequest) {
Object nextObject = thePathAndRef.getRef();
/*
* A search parameter on an extension field that contains
@ -142,35 +145,41 @@ public class ResourceLinkExtractor {
nextId = nextValue.getResource().getIdElement();
}
if (nextId.isEmpty() || nextId.getValue().startsWith("#")) {
// This is a blank or contained resource reference
return;
}
} else if (nextObject instanceof IBaseResource) {
nextId = ((IBaseResource) nextObject).getIdElement();
if (nextId == null || nextId.hasIdPart() == false) {
return;
}
} else if (myContext.getElementDefinition((Class<? extends IBase>) nextObject.getClass()).getName().equals("uri")) {
return;
} else if (theResourceType.equals("Consent") && nextPathAndRef.getPath().equals("Consent.source")) {
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
// nextId = ((IBaseResource) nextObject).getIdElement().toUnqualified();
return;
} else {
if (!theMultiType) {
if (nextSpDef.getName().equals("sourceuri")) {
@SuppressWarnings("unchecked")
Class<? extends IBase> clazz = (Class<? extends IBase>) nextObject.getClass();
if (myContext.getElementDefinition(clazz).getName().equals("uri")) {
return;
} else if (theResourceType.equals("Consent") && thePathAndRef.getPath().equals("Consent.source")) {
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
return;
} else {
if (!theMultiType) {
if (theRuntimeSearchParam.getName().equals("sourceuri")) {
return;
}
throw new ConfigurationException("Search param " + theRuntimeSearchParam.getName() + " is of unexpected datatype: " + nextObject.getClass());
} else {
return;
}
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
} else {
return;
}
}
theParams.myPopulatedResourceLinkParameters.add(nextSpDef.getName());
if (nextId == null ||
nextId.isEmpty() ||
// nextId.hasIdPart() == false ||
nextId.getValue().startsWith("#") ||
nextId.getValue().startsWith("urn:")) {
return;
}
theParams.myPopulatedResourceLinkParameters.add(theRuntimeSearchParam.getName());
if (LogicalReferenceHelper.isLogicalReference(myModelConfig, nextId)) {
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
ResourceLink resourceLink = new ResourceLink(thePathAndRef.getPath(), theEntity, nextId, theUpdateTime);
if (theParams.myLinks.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
@ -180,7 +189,7 @@ public class ResourceLinkExtractor {
String baseUrl = nextId.getBaseUrl();
String typeString = nextId.getResourceType();
if (isBlank(typeString)) {
String msg = "Invalid resource reference found at path[" + theNextPathsUnsplit + "] - Does not contain resource type - " + nextId.getValue();
String msg = "Invalid resource reference found at path[" + thePath + "] - Does not contain resource type - " + nextId.getValue();
if (theFailOnInvalidReference) {
throw new InvalidRequestException(msg);
} else {
@ -192,7 +201,7 @@ public class ResourceLinkExtractor {
try {
resourceDefinition = myContext.getResourceDefinition(typeString);
} catch (DataFormatException e) {
String msg = "Invalid resource reference found at path[" + theNextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextId.getValue();
String msg = "Invalid resource reference found at path[" + thePath + "] - Resource type is unknown or not supported on this server - " + nextId.getValue();
if (theFailOnInvalidReference) {
throw new InvalidRequestException(msg);
} else {
@ -201,12 +210,18 @@ public class ResourceLinkExtractor {
}
}
if (theRuntimeSearchParam.hasTargets()) {
if (!theRuntimeSearchParam.getTargets().contains(typeString)) {
return;
}
}
if (isNotBlank(baseUrl)) {
if (!myModelConfig.getTreatBaseUrlsAsLocal().contains(baseUrl) && !myModelConfig.isAllowExternalReferences()) {
String msg = myContext.getLocalizer().getMessage(BaseSearchParamExtractor.class, "externalReferenceNotAllowed", nextId.getValue());
throw new InvalidRequestException(msg);
} else {
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
ResourceLink resourceLink = new ResourceLink(thePathAndRef.getPath(), theEntity, nextId, theUpdateTime);
if (theParams.myLinks.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
@ -217,7 +232,7 @@ public class ResourceLinkExtractor {
Class<? extends IBaseResource> type = resourceDefinition.getImplementingClass();
String id = nextId.getIdPart();
if (StringUtils.isBlank(id)) {
String msg = "Invalid resource reference found at path[" + theNextPathsUnsplit + "] - Does not contain resource ID - " + nextId.getValue();
String msg = "Invalid resource reference found at path[" + thePath + "] - Does not contain resource ID - " + nextId.getValue();
if (theFailOnInvalidReference) {
throw new InvalidRequestException(msg);
} else {
@ -227,15 +242,19 @@ public class ResourceLinkExtractor {
}
theResourceLinkResolver.validateTypeOrThrowException(type);
ResourceLink resourceLink = createResourceLink(theEntity, theUpdateTime, theResourceLinkResolver, nextSpDef, theNextPathsUnsplit, nextPathAndRef, nextId, typeString, type, id, theRequest);
if (resourceLink == null) return;
ResourceLink resourceLink = createResourceLink(theEntity, theUpdateTime, theResourceLinkResolver, theRuntimeSearchParam, thePath, thePathAndRef, nextId, typeString, type, id, theRequest);
if (resourceLink == null) {
return;
}
theParams.myLinks.add(resourceLink);
}
private ResourceLink createResourceLink(ResourceTable theEntity, Date theUpdateTime, IResourceLinkResolver theResourceLinkResolver, RuntimeSearchParam nextSpDef, String theNextPathsUnsplit, PathAndRef nextPathAndRef, IIdType theNextId, String theTypeString, Class<? extends IBaseResource> theType, String theId, RequestDetails theRequest) {
ResourceTable targetResource = theResourceLinkResolver.findTargetResource(nextSpDef, theNextPathsUnsplit, theNextId, theTypeString, theType, theId, theRequest);
if (targetResource == null) return null;
if (targetResource == null) {
return null;
}
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, targetResource, theUpdateTime);
return resourceLink;
}