Merge pull request #2141 from jamesagnew/im_20201020_package_installer_enhancements
Enable package installer to load non-Conformance resources
This commit is contained in:
commit
fd46d0965f
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 2141
|
||||||
|
title: "The Package Installer has been enhanced to allow resources that do not have a url element to be loaded
|
||||||
|
from a package. Resources without url will instead use identifier element."
|
|
@ -20,6 +20,9 @@ package ca.uhn.fhir.jpa.packages;
|
||||||
* #L%
|
* #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.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
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.IBase;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
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.IPackageCacheManager;
|
||||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -384,9 +388,12 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
|
||||||
} else if (resource.getClass().getSimpleName().equals("Subscription")) {
|
} else if (resource.getClass().getSimpleName().equals("Subscription")) {
|
||||||
String id = extractIdFromSubscription(resource);
|
String id = extractIdFromSubscription(resource);
|
||||||
return SearchParameterMap.newSynchronous().add("_id", new TokenParam(id));
|
return SearchParameterMap.newSynchronous().add("_id", new TokenParam(id));
|
||||||
} else {
|
} else if (resourceHasUrlElement(resource)) {
|
||||||
String url = extractUniqueUrlFromMetadataResource(resource);
|
String url = extractUniqueUrlFromMetadataResource(resource);
|
||||||
return SearchParameterMap.newSynchronous().add("url", new UriParam(url));
|
return SearchParameterMap.newSynchronous().add("url", new UriParam(url));
|
||||||
|
} else {
|
||||||
|
TokenParam identifierToken = extractIdentifierFromOtherResourceTypes(resource);
|
||||||
|
return SearchParameterMap.newSynchronous().add("identifier", identifierToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,6 +419,26 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
|
||||||
return (String) asPrimitiveType.getValue();
|
return (String) asPrimitiveType.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TokenParam extractIdentifierFromOtherResourceTypes(IBaseResource resource) {
|
||||||
|
FhirTerser terser = myFhirContext.newTerser();
|
||||||
|
Identifier identifier = (Identifier) terser.getSingleValueOrNull(resource, "identifier");
|
||||||
|
if (identifier != null) {
|
||||||
|
return new TokenParam(identifier.getSystem(), identifier.getValue());
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Resources in a package must have a url or identifier to be loaded by the package installer.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@VisibleForTesting
|
||||||
void setFhirContextForUnitTest(FhirContext theCtx) {
|
void setFhirContextForUnitTest(FhirContext theCtx) {
|
||||||
myFhirContext = theCtx;
|
myFhirContext = theCtx;
|
||||||
|
|
|
@ -11,7 +11,6 @@ import ca.uhn.fhir.jpa.model.entity.NpmPackageEntity;
|
||||||
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionEntity;
|
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionEntity;
|
||||||
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionResourceEntity;
|
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionResourceEntity;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
|
@ -48,6 +47,7 @@ import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -61,6 +61,7 @@ import static org.hamcrest.Matchers.not;
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class NpmTestR4 extends BaseJpaR4Test {
|
public class NpmTestR4 extends BaseJpaR4Test {
|
||||||
|
|
||||||
|
@ -236,6 +237,59 @@ 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<String> 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_NoIdentifierNoUrl() throws Exception {
|
||||||
|
myDaoConfig.setAllowExternalReferences(true);
|
||||||
|
|
||||||
|
byte[] bytes = loadClasspathBytes("/packages/test-missing-identifier-package.tgz");
|
||||||
|
myFakeNpmServlet.myResponses.put("/test-organizations/1.0.0", bytes);
|
||||||
|
|
||||||
|
List<String> 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);
|
||||||
|
try {
|
||||||
|
PackageInstallOutcomeJson outcome = igInstaller.install(spec);
|
||||||
|
fail();
|
||||||
|
} catch (ImplementationGuideInstallationException theE) {
|
||||||
|
assertThat(theE.getMessage(), containsString("Resources in a package must have a url or identifier to be loaded by the package installer."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInstallR4Package_DraftResourcesNotInstalled() throws Exception {
|
public void testInstallR4Package_DraftResourcesNotInstalled() throws Exception {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue