diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java index 46256602d0a..4cb69ff28d9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java @@ -20,6 +20,9 @@ package ca.uhn.fhir.jpa.packages; * #L% */ +import ca.uhn.fhir.context.BaseRuntimeChildDefinition; +import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; +import ca.uhn.fhir.context.BaseRuntimeElementDefinition; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.support.IValidationSupport; @@ -46,6 +49,7 @@ import org.apache.commons.lang3.Validate; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.utilities.cache.IPackageCacheManager; import org.hl7.fhir.utilities.cache.NpmPackage; import org.slf4j.Logger; @@ -384,9 +388,12 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc { } else if (resource.getClass().getSimpleName().equals("Subscription")) { String id = extractIdFromSubscription(resource); return SearchParameterMap.newSynchronous().add("_id", new TokenParam(id)); - } else { + } else if (resourceHasUrlElement(resource)) { String url = extractUniqueUrlFromMetadataResource(resource); return SearchParameterMap.newSynchronous().add("url", new UriParam(url)); + } else { + TokenParam identifierToken = extractIdentifierFromOtherResourceTypes(resource); + return SearchParameterMap.newSynchronous().add("identifier", identifierToken); } } @@ -412,6 +419,22 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc { return (String) asPrimitiveType.getValue(); } + private TokenParam extractIdentifierFromOtherResourceTypes(IBaseResource resource) { + FhirTerser terser = myFhirContext.newTerser(); + Identifier myIdentifier = (Identifier) terser.getSingleValueOrNull(resource, "identifier"); + return new TokenParam(myIdentifier.getSystem(), myIdentifier.getValue()); + } + + private boolean resourceHasUrlElement(IBaseResource resource) { + BaseRuntimeElementDefinition def = myFhirContext.getElementDefinition(resource.getClass()); + if (!(def instanceof BaseRuntimeElementCompositeDefinition)) { + throw new IllegalArgumentException("Resource is not a composite type: " + resource.getClass().getName()); + } + BaseRuntimeElementCompositeDefinition currentDef = (BaseRuntimeElementCompositeDefinition) def; + BaseRuntimeChildDefinition nextDef = currentDef.getChildByName("url"); + return nextDef != null; + } + @VisibleForTesting void setFhirContextForUnitTest(FhirContext theCtx) { myFhirContext = theCtx; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmTestR4.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmTestR4.java index bee6c8ffbec..ac78da94fb6 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmTestR4.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmTestR4.java @@ -48,6 +48,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -236,6 +237,40 @@ public class NpmTestR4 extends BaseJpaR4Test { }); } + @Test + public void testInstallR4Package_NonConformanceResources() throws Exception { + myDaoConfig.setAllowExternalReferences(true); + + byte[] bytes = loadClasspathBytes("/packages/test-organizations-package.tgz"); + myFakeNpmServlet.myResponses.put("/test-organizations/1.0.0", bytes); + + List resourceList = new ArrayList<>(); + resourceList.add("Organization"); + PackageInstallationSpec spec = new PackageInstallationSpec().setName("test-organizations").setVersion("1.0.0").setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + spec.setInstallResourceTypes(resourceList); + PackageInstallOutcomeJson outcome = igInstaller.install(spec); + assertEquals(3, outcome.getResourcesInstalled().get("Organization")); + + // Be sure no further communication with the server + JettyUtil.closeServer(myServer); + + // Search for the installed resources + runInTransaction(() -> { + SearchParameterMap map = SearchParameterMap.newSynchronous(); + map.add(Organization.SP_IDENTIFIER, new TokenParam("https://github.com/synthetichealth/synthea", "organization1")); + IBundleProvider result = myOrganizationDao.search(map); + assertEquals(1, result.sizeOrThrowNpe()); + map = SearchParameterMap.newSynchronous(); + map.add(Organization.SP_IDENTIFIER, new TokenParam("https://github.com/synthetichealth/synthea", "organization2")); + result = myOrganizationDao.search(map); + assertEquals(1, result.sizeOrThrowNpe()); + map = SearchParameterMap.newSynchronous(); + map.add(Organization.SP_IDENTIFIER, new TokenParam("https://github.com/synthetichealth/synthea", "organization3")); + result = myOrganizationDao.search(map); + assertEquals(1, result.sizeOrThrowNpe()); + }); + + } @Test public void testInstallR4Package_DraftResourcesNotInstalled() throws Exception { diff --git a/hapi-fhir-jpaserver-base/src/test/resources/packages/test-organizations-package.tgz b/hapi-fhir-jpaserver-base/src/test/resources/packages/test-organizations-package.tgz new file mode 100644 index 00000000000..a3f53110d0c Binary files /dev/null and b/hapi-fhir-jpaserver-base/src/test/resources/packages/test-organizations-package.tgz differ