diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2590-preserve-the-ID-value-of-the-resources-in-the-package-loader.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2590-preserve-the-ID-value-of-the-resources-in-the-package-loader.yaml new file mode 100644 index 00000000000..239cc70a772 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2590-preserve-the-ID-value-of-the-resources-in-the-package-loader.yaml @@ -0,0 +1,5 @@ +--- +type: add +issue: 2590 +title: "When resources are created using package load, the new resources will use the same IDs as were provided in with the resource definitions in the package, if they exist. +If the ids are numeric, a prefix of 'npm-' will be added." 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 7c044f667db..d3d3bbda7f3 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 @@ -52,6 +52,7 @@ import com.google.gson.JsonElement; 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.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.utilities.npm.IPackageCacheManager; @@ -329,11 +330,22 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc { ourLog.info("Creating new resource matching {}", map.toNormalizedQueryString(myFhirContext)); theOutcome.incrementResourcesInstalled(myFhirContext.getResourceType(theResource)); - createResource(dao, theResource); + IIdType id = theResource.getIdElement(); + + if (id.isEmpty()) { + createResource(dao, theResource); + ourLog.info("Created resource with new id"); + } else { + if (id.isIdPartValidLong()) { + String newIdPart = "npm-" + id.getIdPart(); + id.setParts(id.getBaseUrl(), id.getResourceType(), newIdPart, id.getVersionIdPart()); + } + updateResource(dao, theResource); + ourLog.info("Created resource with existing id"); + } } else { - - ourLog.info("Updating existing resource matching {}", map.toNormalizedQueryString(myFhirContext)); + ourLog.info("Updating existing resource matching {}", map.toNormalizedQueryString(myFhirContext)); theResource.setId(searchResult.getResources(0, 1).get(0).getIdElement().toUnqualifiedVersionless()); DaoMethodOutcome outcome = updateResource(dao, theResource); if (!outcome.isNop()) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java index ec088316919..69179d6839c 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java @@ -259,9 +259,36 @@ public class NpmR4Test extends BaseJpaR4Test { map.add(StructureDefinition.SP_URL, new UriParam("http://hl7.org/fhir/uv/shorthand/CodeSystem/shorthand-code-system")); IBundleProvider result = myCodeSystemDao.search(map); assertEquals(1, result.sizeOrThrowNpe()); + IBaseResource resource = result.getResources(0, 1).get(0); + assertEquals("CodeSystem/shorthand-code-system/_history/1", resource.getIdElement().toString()); }); } + @Test + public void testNumericIdsInstalledWithNpmPrefix() throws Exception { + myDaoConfig.setAllowExternalReferences(true); + + // Load a copy of hl7.fhir.uv.shorthand-0.12.0, but with id set to 1 instead of "shorthand-code-system" + byte[] bytes = loadClasspathBytes("/packages/hl7.fhir.uv.shorthand-0.13.0.tgz"); + myFakeNpmServlet.myResponses.put("/hl7.fhir.uv.shorthand/0.13.0", bytes); + + PackageInstallationSpec spec = new PackageInstallationSpec().setName("hl7.fhir.uv.shorthand").setVersion("0.13.0").setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + PackageInstallOutcomeJson outcome = myPackageInstallerSvc.install(spec); + // Be sure no further communication with the server + JettyUtil.closeServer(myServer); + + // Search for the installed resource + runInTransaction(() -> { + SearchParameterMap map = SearchParameterMap.newSynchronous(); + map.add(StructureDefinition.SP_URL, new UriParam("http://hl7.org/fhir/uv/shorthand/CodeSystem/shorthand-code-system")); + IBundleProvider result = myCodeSystemDao.search(map); + assertEquals(1, result.sizeOrThrowNpe()); + IBaseResource resource = result.getResources(0, 1).get(0); + assertEquals("CodeSystem/npm-1/_history/1", resource.getIdElement().toString()); + }); + + } + @Test public void testInstallR4Package_NonConformanceResources() throws Exception { myDaoConfig.setAllowExternalReferences(true); diff --git a/hapi-fhir-jpaserver-base/src/test/resources/packages/hl7.fhir.uv.shorthand-0.13.0.tgz b/hapi-fhir-jpaserver-base/src/test/resources/packages/hl7.fhir.uv.shorthand-0.13.0.tgz new file mode 100644 index 00000000000..139cae87f93 Binary files /dev/null and b/hapi-fhir-jpaserver-base/src/test/resources/packages/hl7.fhir.uv.shorthand-0.13.0.tgz differ