diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 0aa7fdaeefb..9161e8419d2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -1550,15 +1550,17 @@ public abstract class BaseHapiFhirDao implements IDao, continue; } - for (IBase nextChild : values) { - IBaseReference nextRef = (IBaseReference) nextChild; - IIdType referencedId = nextRef.getReferenceElement(); - if (!isBlank(referencedId.getResourceType())) { - if (!isLogicalReference(referencedId)) { - if (!referencedId.getValue().contains("?")) { - if (!validTypes.contains(referencedId.getResourceType())) { - throw new UnprocessableEntityException( - "Invalid reference found at path '" + newPath + "'. Resource type '" + referencedId.getResourceType() + "' is not valid for this path"); + if (getConfig().isEnforceReferenceTargetTypes()) { + for (IBase nextChild : values) { + IBaseReference nextRef = (IBaseReference) nextChild; + IIdType referencedId = nextRef.getReferenceElement(); + if (!isBlank(referencedId.getResourceType())) { + if (!isLogicalReference(referencedId)) { + if (!referencedId.getValue().contains("?")) { + if (!validTypes.contains(referencedId.getResourceType())) { + throw new UnprocessableEntityException( + "Invalid reference found at path '" + newPath + "'. Resource type '" + referencedId.getResourceType() + "' is not valid for this path"); + } } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 383df71a802..ee89906d4d5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -26,9 +26,9 @@ import java.util.*; * 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. @@ -142,6 +142,7 @@ public class DaoConfig { private List myWarmCacheEntries = new ArrayList<>(); private boolean myDisableHashBasedSearches; private boolean myEnableInMemorySubscriptionMatching = true; + private boolean myEnforceReferenceTargetTypes = true; private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC; /** @@ -161,6 +162,26 @@ public class DaoConfig { } } + /** + * If set to true (default is true) when a resource is being persisted, + * the target resource types of references will be validated to ensure that they + * are appropriate for the field containing the reference. This is generally a good idea + * because invalid reference target types may not be searchable. + */ + public boolean isEnforceReferenceTargetTypes() { + return myEnforceReferenceTargetTypes; + } + + /** + * If set to true (default is true) when a resource is being persisted, + * the target resource types of references will be validated to ensure that they + * are appropriate for the field containing the reference. This is generally a good idea + * because invalid reference target types may not be searchable. + */ + public void setEnforceReferenceTargetTypes(boolean theEnforceReferenceTargetTypes) { + myEnforceReferenceTargetTypes = theEnforceReferenceTargetTypes; + } + /** * If a non-null value is supplied (default is null), a default * for the _total parameter may be specified here. For example, @@ -1392,6 +1413,7 @@ public class DaoConfig { /** * If set to true (default is true) the server will match incoming resources against active subscriptions * and send them to the subscription channel. If set to false no matching or sending occurs. + * * @since 3.7.0 */ @@ -1402,6 +1424,7 @@ public class DaoConfig { /** * If set to true (default is true) the server will match incoming resources against active subscriptions * and send them to the subscription channel. If set to false no matching or sending occurs. + * * @since 3.7.0 */ diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java index d9b1472adc4..47c1164da76 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java @@ -73,6 +73,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test { myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences()); myDaoConfig.setTreatReferencesAsLogical(new DaoConfig().getTreatReferencesAsLogical()); myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete()); + myDaoConfig.setEnforceReferenceTargetTypes(new DaoConfig().isEnforceReferenceTargetTypes()); } private void assertGone(IIdType theId) { @@ -945,6 +946,13 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test { assertEquals("Resource Organization/testCreateWithIllegalReference not found, specified in path: Patient.managingOrganization", e.getMessage()); } + // Disable validation + myDaoConfig.setEnforceReferenceTargetTypes(false); + Patient p = new Patient(); + p.getManagingOrganization().setReferenceElement(id1); + myPatientDao.create(p, mySrd); + + } @Test diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2801f4c2697..d9cfd72893d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -73,6 +73,10 @@ (e.g. "Patient?identifier=&identifier=b" returned no results even if resources should have matched. Thanks to @mingdatacom for reporting! + + A new config setting has been added to the JPA DaoConfig that disables validation + of the resource type for target resources in references. +