Add R4 code to CLI

This commit is contained in:
James 2017-08-05 06:22:06 -04:00
parent 1a95ba3b65
commit ee360f5376
11 changed files with 259 additions and 50 deletions

View File

@ -57,6 +57,8 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
version = FhirVersionEnum.DSTU2;
} else if ("dstu3".equals(specVersion)) {
version = FhirVersionEnum.DSTU3;
} else if ("r4".equals(specVersion)) {
version = FhirVersionEnum.R4;
} else {
throw new ParseException("Unknown spec version: " + specVersion);
}

View File

@ -114,6 +114,9 @@ public class ExampleDataUploader extends BaseCommand {
specUrl = "http://hl7.org/fhir/dstu2/examples-json.zip";
break;
case DSTU3:
specUrl = "http://hl7.org/fhir/STU3/examples-json.zip";
break;
case R4:
specUrl = "http://build.fhir.org/examples-json.zip";
break;
default:
@ -140,7 +143,7 @@ public class ExampleDataUploader extends BaseCommand {
if (suppliedFile.isDirectory()) {
Collection<File> inputFiles;
inputFiles = FileUtils.listFiles(suppliedFile, new String[] { "zip" }, false);
inputFiles = FileUtils.listFiles(suppliedFile, new String[]{"zip"}, false);
for (File inputFile : inputFiles) {
IBaseBundle bundle = getBundleFromFile(limit, inputFile, ctx);
@ -197,21 +200,23 @@ public class ExampleDataUploader extends BaseCommand {
}
private IBaseBundle getBundleFromFile(Integer theLimit, File theSuppliedFile, FhirContext theCtx) throws ParseException, UnsupportedEncodingException, IOException {
private IBaseBundle getBundleFromFile(Integer theLimit, File theSuppliedFile, FhirContext theCtx) throws ParseException, IOException {
switch (theCtx.getVersion().getVersion()) {
case DSTU2:
return getBundleFromFileDstu2(theLimit, theSuppliedFile, theCtx);
case DSTU3:
return getBundleFromFileDstu3(theLimit, theSuppliedFile, theCtx);
case R4:
return getBundleFromFileDstu3(theLimit, theSuppliedFile, theCtx);
default:
throw new ParseException("Invalid spec version for this command: " + theCtx.getVersion().getVersion());
}
}
private void sendBundleToTarget(String targetServer, FhirContext ctx, IBaseBundle bundle) throws Exception, IOException {
private void sendBundleToTarget(String targetServer, FhirContext ctx, IBaseBundle bundle) throws Exception {
List<IBaseResource> resources = BundleUtil.toListOfResources(ctx, bundle);
for (Iterator<IBaseResource> iter = resources.iterator(); iter.hasNext();) {
for (Iterator<IBaseResource> iter = resources.iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next();
String nextType = ctx.getResourceDefinition(next).getName();
if (nextType.endsWith("Definition")) {
@ -223,13 +228,13 @@ public class ExampleDataUploader extends BaseCommand {
}
}
List<IBaseResource> subResourceList = new ArrayList<IBaseResource>();
List<IBaseResource> subResourceList = new ArrayList<>();
while (resources.size() > 0) {
IBaseResource nextAddedResource = resources.remove(0);
subResourceList.add(nextAddedResource);
Set<String> checkedTargets = new HashSet<String>();
Set<String> checkedTargets = new HashSet<>();
for (int i = 0; i < subResourceList.size(); i++) {
IBaseResource nextCandidateSource = subResourceList.get(i);
@ -319,6 +324,9 @@ public class ExampleDataUploader extends BaseCommand {
case DSTU3:
processBundleDstu3(ctx, (org.hl7.fhir.dstu3.model.Bundle) bundle);
break;
case R4:
processBundleR4(ctx, (org.hl7.fhir.r4.model.Bundle) bundle);
break;
default:
throw new IllegalStateException();
}
@ -329,7 +337,7 @@ public class ExampleDataUploader extends BaseCommand {
Map<String, Integer> ids = new HashMap<String, Integer>();
Set<String> fullIds = new HashSet<String>();
for (Iterator<Entry> iterator = bundle.getEntry().iterator(); iterator.hasNext();) {
for (Iterator<Entry> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
Entry next = iterator.next();
// DataElement have giant IDs that seem invalid, need to investigate this..
@ -355,7 +363,7 @@ public class ExampleDataUploader extends BaseCommand {
}
}
Set<String> qualIds = new TreeSet<String>();
for (Iterator<Entry> iterator = bundle.getEntry().iterator(); iterator.hasNext();) {
for (Iterator<Entry> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
Entry next = iterator.next();
if (next.getResource().getId().getIdPart() != null) {
String nextId = next.getResource().getId().getValue();
@ -409,7 +417,7 @@ public class ExampleDataUploader extends BaseCommand {
Map<String, Integer> ids = new HashMap<String, Integer>();
Set<String> fullIds = new HashSet<String>();
for (Iterator<BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext();) {
for (Iterator<BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
BundleEntryComponent next = iterator.next();
// DataElement have giant IDs that seem invalid, need to investigate this..
@ -435,7 +443,7 @@ public class ExampleDataUploader extends BaseCommand {
}
}
Set<String> qualIds = new TreeSet<String>();
for (Iterator<BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext();) {
for (Iterator<BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
BundleEntryComponent next = iterator.next();
if (next.getResource().getIdElement().getIdPart() != null) {
String nextId = next.getResource().getIdElement().getValue();
@ -484,6 +492,72 @@ public class ExampleDataUploader extends BaseCommand {
}
private void processBundleR4(FhirContext ctx, org.hl7.fhir.r4.model.Bundle bundle) {
Map<String, Integer> ids = new HashMap<String, Integer>();
Set<String> fullIds = new HashSet<String>();
for (Iterator<org.hl7.fhir.r4.model.Bundle.BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent next = iterator.next();
// DataElement have giant IDs that seem invalid, need to investigate this..
if ("Subscription".equals(next.getResource().getResourceType()) || "DataElement".equals(next.getResource().getResourceType())
|| "OperationOutcome".equals(next.getResource().getResourceType()) || "OperationDefinition".equals(next.getResource().getResourceType())) {
ourLog.info("Skipping " + next.getResource().getResourceType() + " example");
iterator.remove();
} else {
IdDt resourceId = new IdDt(next.getResource().getResourceType() + "/EX" + next.getResource().getIdElement().getIdPart());
if (!fullIds.add(resourceId.toUnqualifiedVersionless().getValue())) {
ourLog.info("Discarding duplicate resource: " + resourceId.getValue());
iterator.remove();
continue;
}
String idPart = resourceId.getIdPart();
if (idPart != null) {
next.getResource().setId(resourceId);
} else {
ourLog.info("Discarding resource with not explicit ID");
iterator.remove();
}
}
}
Set<String> qualIds = new TreeSet<String>();
for (Iterator<org.hl7.fhir.r4.model.Bundle.BundleEntryComponent> iterator = bundle.getEntry().iterator(); iterator.hasNext(); ) {
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent next = iterator.next();
if (next.getResource().getIdElement().getIdPart() != null) {
String nextId = next.getResource().getIdElement().getValue();
next.getRequest().setMethod(org.hl7.fhir.r4.model.Bundle.HTTPVerb.PUT);
next.getRequest().setUrl(nextId);
}
}
int goodRefs = 0;
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent next : bundle.getEntry()) {
List<ResourceReferenceInfo> refs = ctx.newTerser().getAllResourceReferences(next.getResource());
for (ResourceReferenceInfo nextRef : refs) {
nextRef.getResourceReference().setResource(null);
String value = nextRef.getResourceReference().getReferenceElement().toUnqualifiedVersionless().getValue();
if (isNotBlank(value)) {
if (!qualIds.contains(value) && !nextRef.getResourceReference().getReferenceElement().isLocal()) {
ourLog.info("Discarding unknown reference: {}", value);
nextRef.getResourceReference().getReferenceElement().setValue(null);
} else {
goodRefs++;
}
}
ourLog.info("Found ref: {}", value);
}
}
ourLog.info("{} good references", goodRefs);
System.gc();
ourLog.info("Final bundle: {} entries", bundle.getEntry().size());
}
private Bundle getBundleFromFileDstu2(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
Bundle bundle = new Bundle();

View File

@ -20,11 +20,9 @@ public class UploadTerminologyCommand extends BaseCommand {
@Override
public String getCommandDescription() {
//@formatter:off
return "Uploads a terminology package (e.g. a SNOMED CT ZIP file) to a HAPI JPA server. "
+ "Note that this command uses a custom operation that is only implemented on HAPI "
+ "JPA servers that have been configured to accept it.";
//@formatter:on
}
@Override

View File

@ -65,6 +65,8 @@ public class ValidationDataUploader extends BaseCommand {
uploadDefinitionsDstu2(targetServer, ctx);
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU3){
uploadDefinitionsDstu3(targetServer, ctx);
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.R4){
uploadDefinitionsR4(targetServer, ctx);
}
}
@ -256,6 +258,95 @@ public class ValidationDataUploader extends BaseCommand {
ourLog.info("Finished uploading definitions to server (took {} ms)", delay);
}
private void uploadDefinitionsR4(String theTargetServer, FhirContext theCtx) throws CommandFailureException {
IGenericClient client = newClient(theCtx, theTargetServer);
ourLog.info("Uploading definitions to server: " + theTargetServer);
long start = System.currentTimeMillis();
int total = 0;
int count = 0;
org.hl7.fhir.r4.model.Bundle bundle;
String vsContents;
try {
theCtx.getVersion().getPathToSchemaDefinitions();
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/r4/model/valueset/"+"valuesets.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = theCtx.newXmlParser().parseResource(org.hl7.fhir.r4.model.Bundle.class, vsContents);
total = bundle.getEntry().size();
count = 1;
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.r4.model.Resource next = i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
int bytes = theCtx.newXmlParser().encodeResourceToString(next).length();
ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[] { count, total, next.getIdElement().getValue(), bytes });
try {
IIdType id = client.update().resource(next).execute().getId();
ourLog.info(" - Got ID: {}", id.getValue());
} catch (UnprocessableEntityException e) {
ourLog.warn("UnprocessableEntityException: " + e.toString());
}
count++;
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/r4/model/valueset/"+"v3-codesystems.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = theCtx.newXmlParser().parseResource(org.hl7.fhir.r4.model.Bundle.class, vsContents);
total = bundle.getEntry().size();
count = 1;
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.r4.model.Resource next = i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
client.update().resource(next).execute();
count++;
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/r4/model/valueset/"+"v2-tables.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = theCtx.newXmlParser().parseResource(org.hl7.fhir.r4.model.Bundle.class, vsContents);
total = bundle.getEntry().size();
count = 1;
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.r4.model.Resource next = i.getResource();
if (next.getIdElement().isIdPartValidLong()) {
next.setIdElement(new org.hl7.fhir.r4.model.IdType("v2-"+ next.getIdElement().getIdPart()));
}
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
client.update().resource(next).execute();
count++;
}
ourLog.info("Finished uploading ValueSets");
uploadDstu3Profiles(theCtx, client, "profiles-resources");
uploadDstu3Profiles(theCtx, client, "profiles-types");
uploadDstu3Profiles(theCtx, client, "profiles-others");
ourLog.info("Finished uploading ValueSets");
long delay = System.currentTimeMillis() - start;
ourLog.info("Finished uploading definitions to server (took {} ms)", delay);
}
private void uploadDstu3Profiles(FhirContext ctx, IGenericClient client, String name) throws CommandFailureException {
int total;
int count;

View File

@ -20,6 +20,10 @@
<artifactId>postgresql</artifactId>
<version>9.4.1212.jre7</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>

View File

@ -6,6 +6,8 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
@ -125,10 +127,10 @@ public class TestRestfulServer extends RestfulServer {
myAppCtx.refresh();
setFhirContext(FhirContext.forR4());
beans = myAppCtx.getBean("myResourceProvidersR4", List.class);
plainProviders.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderDstu3.class));
plainProviders.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class));
systemDao = myAppCtx.getBean("mySystemDaoR4", IFhirSystemDao.class);
etagSupport = ETagSupportEnum.ENABLED;
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class));
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, myAppCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription(implDesc);
setServerConformanceProvider(confProvider);
plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderR4.class));

View File

@ -57,4 +57,8 @@ public class CommonConfig {
return new HolyFooCowInterceptor();
}
public static boolean isLocalTestMode(){
return "true".equalsIgnoreCase(System.getProperty("testmode.local"));
}
}

View File

@ -8,6 +8,7 @@ import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.PostgreSQL94Dialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Value;
@ -70,8 +71,12 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
@Bean(name = "myPersistenceDataSourceDstu1", destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource retVal = new BasicDataSource();
if (CommonConfig.isLocalTestMode()) {
retVal.setUrl("jdbc:derby:memory:fhirtest_dstu2;create=true");
} else {
retVal.setDriver(new org.postgresql.Driver());
retVal.setUrl("jdbc:postgresql://localhost/fhirtest_dstu2");
}
retVal.setUsername(myDbUsername);
retVal.setPassword(myDbPassword);
return retVal;
@ -97,7 +102,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
private Properties jpaProperties() {
Properties extraProperties = new Properties();
if (CommonConfig.isLocalTestMode()) {
extraProperties.put("hibernate.dialect", DerbyTenSevenDialect.class.getName());
} else {
extraProperties.put("hibernate.dialect", PostgreSQL94Dialect.class.getName());
}
extraProperties.put("hibernate.format_sql", "false");
extraProperties.put("hibernate.show_sql", "false");
extraProperties.put("hibernate.hbm2ddl.auto", "update");

View File

@ -7,6 +7,7 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.PostgreSQL94Dialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowire;
@ -74,8 +75,12 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
@Bean(name = "myPersistenceDataSourceDstu3", destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource retVal = new BasicDataSource();
if (CommonConfig.isLocalTestMode()) {
retVal.setUrl("jdbc:derby:memory:fhirtest_dstu3;create=true");
} else {
retVal.setDriver(new org.postgresql.Driver());
retVal.setUrl("jdbc:postgresql://localhost/fhirtest_dstu3");
}
retVal.setUsername(myDbUsername);
retVal.setPassword(myDbPassword);
return retVal;
@ -94,7 +99,11 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
private Properties jpaProperties() {
Properties extraProperties = new Properties();
if (CommonConfig.isLocalTestMode()) {
extraProperties.put("hibernate.dialect", DerbyTenSevenDialect.class.getName());
} else {
extraProperties.put("hibernate.dialect", PostgreSQL94Dialect.class.getName());
}
extraProperties.put("hibernate.format_sql", "false");
extraProperties.put("hibernate.show_sql", "false");
extraProperties.put("hibernate.hbm2ddl.auto", "update");

View File

@ -7,6 +7,8 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.PostgreSQL94Dialect;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowire;
@ -74,8 +76,12 @@ public class TestR4Config extends BaseJavaConfigR4 {
@Bean(name = "myPersistenceDataSourceR4", destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource retVal = new BasicDataSource();
if (CommonConfig.isLocalTestMode()) {
retVal.setUrl("jdbc:derby:memory:fhirtest_r4;create=true");
} else {
retVal.setDriver(new org.postgresql.Driver());
retVal.setUrl("jdbc:postgresql://localhost/fhirtest_r4");
}
retVal.setUsername(myDbUsername);
retVal.setPassword(myDbPassword);
return retVal;
@ -94,7 +100,11 @@ public class TestR4Config extends BaseJavaConfigR4 {
private Properties jpaProperties() {
Properties extraProperties = new Properties();
extraProperties.put("hibernate.dialect", PostgreSQL95Dialect.class.getName());
if (CommonConfig.isLocalTestMode()) {
extraProperties.put("hibernate.dialect", DerbyTenSevenDialect.class.getName());
} else {
extraProperties.put("hibernate.dialect", PostgreSQL94Dialect.class.getName());
}
extraProperties.put("hibernate.format_sql", "false");
extraProperties.put("hibernate.show_sql", "false");
extraProperties.put("hibernate.hbm2ddl.auto", "update");

View File

@ -26,6 +26,8 @@ public class UhnFhirTestApp {
System.setProperty("fhir.lucene.location.dstu2", "./target/testlucene_dstu2");
System.setProperty("fhir.db.location.dstu3", "./target/fhirtest_dstu3");
System.setProperty("fhir.lucene.location.dstu3", "./target/testlucene_dstu3");
System.setProperty("fhir.db.location.r4", "./target/fhirtest_r4");
System.setProperty("fhir.lucene.location.r4", "./target/testlucene_r4");
System.setProperty("fhir.db.location.tdl2", "./target/testdb_tdl2");
System.setProperty("fhir.lucene.location.tdl2", "./target/testlucene_tdl2");
System.setProperty("fhir.db.location.tdl3", "./target/testdb_tdl3");
@ -33,9 +35,13 @@ public class UhnFhirTestApp {
System.setProperty("fhir.baseurl.dstu2", base);
System.setProperty("fhir.baseurl.dstu1", base.replace("Dstu2", "Dstu1"));
System.setProperty("fhir.baseurl.dstu3", base.replace("Dstu2", "Dstu3"));
System.setProperty("fhir.baseurl.r4", base.replace("Dstu2", "R4"));
System.setProperty("fhir.baseurl.tdl2", base.replace("baseDstu2", "testDataLibraryDstu2"));
System.setProperty("fhir.baseurl.tdl3", base.replace("baseDstu2", "testDataLibraryStu3"));
System.setProperty("fhir.tdlpass", "aa,bb");
System.setProperty("fhir.db.username", "SA");
System.setProperty("fhir.db.password", "SA");
System.setProperty("testmode.local", "true");
Server server = new Server(myPort);