Merge branch 'master' into con16_subscriptions

This commit is contained in:
James Agnew 2017-09-10 08:49:28 -07:00
commit 415f2bc72d
86 changed files with 8740 additions and 10003 deletions

View File

@ -8,6 +8,7 @@ import javax.servlet.ServletException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.*;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;

View File

@ -2,7 +2,7 @@ package example;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import ca.uhn.fhir.context.FhirContext;

View File

@ -1,28 +1,8 @@
package ca.uhn.fhir.cli;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.cli.*;
import org.apache.commons.io.*;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.fusesource.jansi.Ansi;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.Bundle.*;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
@ -39,11 +19,280 @@ import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class ExampleDataUploader extends BaseCommand {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleDataUploader.class);
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 getBundleFromFileR4(theLimit, theSuppliedFile, theCtx);
default:
throw new ParseException("Invalid spec version for this command: " + theCtx.getVersion().getVersion());
}
}
private Bundle getBundleFromFileDstu2(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
Bundle bundle = new Bundle();
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (DataFormatException e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
continue;
}
for (IBase nextResource : resources) {
if (!ctx.getResourceDefinition(parsed).getName().equals("Bundle") && ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource((IResource) nextResource);
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource((IResource) parsed);
}
}
return bundle;
}
@SuppressWarnings("unchecked")
private org.hl7.fhir.dstu3.model.Bundle getBundleFromFileDstu3(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
org.hl7.fhir.dstu3.model.Bundle bundle = new org.hl7.fhir.dstu3.model.Bundle();
bundle.setType(BundleType.TRANSACTION);
FhirValidator val = ctx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator(new DefaultProfileValidationSupport()));
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (Exception e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
ValidationResult result = val.validateWithResult(parsed);
if (result.isSuccessful() == false) {
ourLog.info("FAILED to validate example {} - {}", nextEntry.getName(), result.toString());
continue;
}
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
continue;
}
for (IBase nextResource : resources) {
if (nextResource == null) {
continue;
}
if (!ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("Bundle")
&& ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("SearchParameter")) {
BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(HTTPVerb.POST);
entry.setResource((Resource) nextResource);
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(HTTPVerb.POST);
entry.setResource((Resource) parsed);
}
}
return bundle;
}
@SuppressWarnings("unchecked")
private org.hl7.fhir.r4.model.Bundle getBundleFromFileR4(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
org.hl7.fhir.r4.model.Bundle bundle = new org.hl7.fhir.r4.model.Bundle();
bundle.setType(org.hl7.fhir.r4.model.Bundle.BundleType.TRANSACTION);
FhirValidator val = ctx.newValidator();
val.registerValidatorModule(new org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator(new org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport()));
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (Exception e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
ValidationResult result = val.validateWithResult(parsed);
if (result.isSuccessful() == false) {
ourLog.info("FAILED to validate example {} - {}", nextEntry.getName(), result.toString());
continue;
}
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
continue;
}
for (IBase nextResource : resources) {
if (nextResource == null) {
continue;
}
if (!ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("Bundle")
&& ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("SearchParameter")) {
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST);
entry.setResource((org.hl7.fhir.r4.model.Resource) nextResource);
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST);
entry.setResource((org.hl7.fhir.r4.model.Resource) parsed);
}
}
return bundle;
}
@Override
public String getCommandDescription() {
return "Downloads the resource example pack from the HL7.org FHIR specification website, and uploads all of the example resources to a given server.";
@ -78,182 +327,9 @@ public class ExampleDataUploader extends BaseCommand {
opt.setRequired(false);
options.addOption(opt);
// opt = new Option("c", "cache", true, "Store a copy of the downloaded example pack on the local disk using a file of the given name. Use this file instead of fetching it from the internet if
// the file already exists.");
// opt.setRequired(false);
// options.addOption(opt);
return options;
}
@Override
public void run(CommandLine theCommandLine) throws Exception {
FhirContext ctx = getSpecVersionContext(theCommandLine);
String targetServer = theCommandLine.getOptionValue("t");
if (isBlank(targetServer)) {
throw new ParseException("No target server (-t) specified");
} else if (targetServer.startsWith("http") == false && targetServer.startsWith("file") == false) {
throw new ParseException("Invalid target server specified, must begin with 'http' or 'file'");
}
Integer limit = null;
String limitString = theCommandLine.getOptionValue('l');
if (isNotBlank(limitString)) {
try {
limit = Integer.parseInt(limitString);
} catch (NumberFormatException e) {
throw new ParseException("Invalid number for limit (-l) option, must be a number: " + limitString);
}
}
String specUrl;
switch (ctx.getVersion().getVersion()) {
case DSTU2:
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:
throw new ParseException("Invalid spec version for this command: " + ctx.getVersion().getVersion());
}
String filepath = theCommandLine.getOptionValue('d');
boolean cacheFile = theCommandLine.hasOption('c');
Collection<File> inputFiles = loadFile(ctx, specUrl, filepath, cacheFile);
for (File inputFile : inputFiles) {
IBaseBundle bundle = getBundleFromFile(limit, inputFile, ctx);
processBundle(ctx, bundle);
sendBundleToTarget(targetServer, ctx, bundle);
}
}
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 getBundleFromFileR4(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 {
List<IBaseResource> resources = BundleUtil.toListOfResources(ctx, bundle);
for (Iterator<IBaseResource> iter = resources.iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next();
String nextType = ctx.getResourceDefinition(next).getName();
if (nextType.endsWith("Definition")) {
iter.remove();
} else if (nextType.contains("ValueSet")) {
iter.remove();
} else if (nextType.equals("CodeSystem")) {
iter.remove();
}
}
List<IBaseResource> subResourceList = new ArrayList<>();
while (resources.size() > 0) {
IBaseResource nextAddedResource = resources.remove(0);
subResourceList.add(nextAddedResource);
Set<String> checkedTargets = new HashSet<>();
for (int i = 0; i < subResourceList.size(); i++) {
IBaseResource nextCandidateSource = subResourceList.get(i);
for (ResourceReferenceInfo nextRef : ctx.newTerser().getAllResourceReferences(nextCandidateSource)) {
String nextRefResourceType = nextRef.getResourceReference().getReferenceElement().getResourceType();
String nextRefIdPart = nextRef.getResourceReference().getReferenceElement().getIdPart();
if (isBlank(nextRefResourceType) || isBlank(nextRefIdPart)) {
nextRef.getResourceReference().setResource(null);
nextRef.getResourceReference().setReference(null);
continue;
}
if (nextRefIdPart.startsWith("EX")) {
nextRefIdPart = nextRefIdPart.substring(2);
}
String nextTarget = nextRefResourceType + "/EX" + nextRefIdPart;
nextRef.getResourceReference().setResource(null);
nextRef.getResourceReference().setReference(nextTarget);
if (checkedTargets.add(nextTarget) == false) {
continue;
}
boolean found = false;
for (int j = 0; j < resources.size(); j++) {
String candidateTarget = resources.get(j).getIdElement().getValue();
if (isNotBlank(nextTarget) && nextTarget.equals(candidateTarget)) {
ourLog.info("Reflexively adding resource {} to bundle as it is a reference target", nextTarget);
subResourceList.add(resources.remove(j));
found = true;
break;
}
}
}
}
if (subResourceList.size() < 10 && resources.size() > 0) {
subResourceList.add(resources.remove(0));
continue;
}
ourLog.info("About to upload {} examples in a transaction, {} remaining", subResourceList.size(), resources.size());
IVersionSpecificBundleFactory bundleFactory = ctx.newBundleFactory();
bundleFactory.initializeBundleFromResourceList(null, subResourceList, null, null, 0, BundleTypeEnum.TRANSACTION);
IBaseResource subBundle = bundleFactory.getResourceBundle();
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(subBundle);
ourLog.info("Final bundle: {}", FileUtils.byteCountToDisplaySize(encoded.length()));
if (targetServer.startsWith("file://")) {
String path = targetServer.substring("file://".length());
ourLog.info("Writing bundle to: {}", path);
File file = new File(path);
if (file.exists()) {
throw new Exception("File already exists: " + file.getAbsolutePath());
}
FileWriter w = new FileWriter(file, false);
w.append(encoded);
w.close();
} else {
ourLog.info("Uploading bundle to server: " + targetServer);
IGenericClient fhirClient = newClient(ctx, targetServer);
fhirClient.registerInterceptor(new GZipContentInterceptor());
long start = System.currentTimeMillis();
try {
fhirClient.transaction().withBundle(encoded).execute();
} catch (BaseServerResponseException e) {
ourLog.error("Failed to upload bundle:HTTP " + e.getStatusCode() + ": " + e.getMessage());
ourLog.error("Failing bundle: {}", encoded);
}
long delay = System.currentTimeMillis() - start;
ourLog.info("Finished uploading bundle to server (took {} ms)", delay);
}
subResourceList.clear();
}
}
private void processBundle(FhirContext ctx, IBaseBundle bundle) {
switch (ctx.getVersion().getVersion()) {
case DSTU2:
@ -496,237 +572,159 @@ public class ExampleDataUploader extends BaseCommand {
}
private Bundle getBundleFromFileDstu2(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
@Override
public void run(CommandLine theCommandLine) throws Exception {
FhirContext ctx = getSpecVersionContext(theCommandLine);
Bundle bundle = new Bundle();
String targetServer = theCommandLine.getOptionValue("t");
if (isBlank(targetServer)) {
throw new ParseException("No target server (-t) specified");
} else if (targetServer.startsWith("http") == false && targetServer.startsWith("file") == false) {
throw new ParseException("Invalid target server specified, must begin with 'http' or 'file'");
}
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
Integer limit = null;
String limitString = theCommandLine.getOptionValue('l');
if (isNotBlank(limitString)) {
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (DataFormatException e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
continue;
}
for (IBase nextResource : resources) {
if (!ctx.getResourceDefinition(parsed).getName().equals("Bundle") && ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource((IResource) nextResource);
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource((IResource) parsed);
limit = Integer.parseInt(limitString);
} catch (NumberFormatException e) {
throw new ParseException("Invalid number for limit (-l) option, must be a number: " + limitString);
}
}
return bundle;
String specUrl;
switch (ctx.getVersion().getVersion()) {
case DSTU2:
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:
throw new ParseException("Invalid spec version for this command: " + ctx.getVersion().getVersion());
}
String filepath = theCommandLine.getOptionValue('d');
boolean cacheFile = theCommandLine.hasOption('c');
Collection<File> inputFiles = loadFile(ctx, specUrl, filepath, cacheFile);
for (File inputFile : inputFiles) {
IBaseBundle bundle = getBundleFromFile(limit, inputFile, ctx);
processBundle(ctx, bundle);
sendBundleToTarget(targetServer, ctx, bundle);
}
}
@SuppressWarnings("unchecked")
private org.hl7.fhir.dstu3.model.Bundle getBundleFromFileDstu3(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
private void sendBundleToTarget(String targetServer, FhirContext ctx, IBaseBundle bundle) throws Exception {
List<IBaseResource> resources = BundleUtil.toListOfResources(ctx, bundle);
org.hl7.fhir.dstu3.model.Bundle bundle = new org.hl7.fhir.dstu3.model.Bundle();
bundle.setType(BundleType.TRANSACTION);
for (Iterator<IBaseResource> iter = resources.iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next();
FhirValidator val = ctx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator(new DefaultProfileValidationSupport()));
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (Exception e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
ValidationResult result = val.validateWithResult(parsed);
if (result.isSuccessful() == false) {
ourLog.info("FAILED to validate example {} - {}", nextEntry.getName(), result.toString());
continue;
}
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
continue;
}
for (IBase nextResource : resources) {
if (nextResource == null) {
continue;
}
if (!ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("Bundle")
&& ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("SearchParameter")) {
BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(HTTPVerb.POST);
entry.setResource((Resource) nextResource);
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(HTTPVerb.POST);
entry.setResource((Resource) parsed);
String nextType = ctx.getResourceDefinition(next).getName();
if (nextType.endsWith("Definition")) {
iter.remove();
} else if (nextType.contains("ValueSet")) {
iter.remove();
} else if (nextType.equals("CodeSystem")) {
iter.remove();
}
}
return bundle;
}
@SuppressWarnings("unchecked")
private org.hl7.fhir.r4.model.Bundle getBundleFromFileR4(Integer limit, File inputFile, FhirContext ctx) throws IOException, UnsupportedEncodingException {
List<IBaseResource> subResourceList = new ArrayList<>();
while (resources.size() > 0) {
org.hl7.fhir.r4.model.Bundle bundle = new org.hl7.fhir.r4.model.Bundle();
bundle.setType(org.hl7.fhir.r4.model.Bundle.BundleType.TRANSACTION);
IBaseResource nextAddedResource = resources.remove(0);
subResourceList.add(nextAddedResource);
FhirValidator val = ctx.newValidator();
val.registerValidatorModule(new org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator(new org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport()));
Set<String> checkedTargets = new HashSet<>();
ZipInputStream zis = new ZipInputStream(FileUtils.openInputStream(inputFile));
byte[] buffer = new byte[2048];
int count = 0;
while (true) {
count++;
if (limit != null && count > limit) {
break;
}
ZipEntry nextEntry = zis.getNextEntry();
if (nextEntry == null) {
break;
}
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
byte[] exampleBytes = bos.toByteArray();
String exampleString = new String(exampleBytes, "UTF-8");
if (ourLog.isTraceEnabled()) {
ourLog.trace("Next example: " + exampleString);
}
IBaseResource parsed;
try {
parsed = ctx.newJsonParser().parseResource(exampleString);
} catch (Exception e) {
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
continue;
}
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
ValidationResult result = val.validateWithResult(parsed);
if (result.isSuccessful() == false) {
ourLog.info("FAILED to validate example {} - {}", nextEntry.getName(), result.toString());
continue;
}
if (ctx.getResourceDefinition(parsed).getName().equals("Bundle")) {
BaseRuntimeChildDefinition entryChildDef = ctx.getResourceDefinition(parsed).getChildByName("entry");
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
for (IBase nextEntry1 : entryChildDef.getAccessor().getValues(parsed)) {
List<IBase> resources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry1);
if (resources == null) {
for (int i = 0; i < subResourceList.size(); i++) {
IBaseResource nextCandidateSource = subResourceList.get(i);
for (ResourceReferenceInfo nextRef : ctx.newTerser().getAllResourceReferences(nextCandidateSource)) {
String nextRefResourceType = nextRef.getResourceReference().getReferenceElement().getResourceType();
String nextRefIdPart = nextRef.getResourceReference().getReferenceElement().getIdPart();
if (isBlank(nextRefResourceType) || isBlank(nextRefIdPart)) {
nextRef.getResourceReference().setResource(null);
nextRef.getResourceReference().setReference(null);
continue;
}
for (IBase nextResource : resources) {
if (nextResource == null) {
continue;
}
if (!ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("Bundle")
&& ctx.getResourceDefinition((Class<? extends IBaseResource>) nextResource.getClass()).getName().equals("SearchParameter")) {
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST);
entry.setResource((org.hl7.fhir.r4.model.Resource) nextResource);
if (nextRefIdPart.startsWith("EX")) {
nextRefIdPart = nextRefIdPart.substring(2);
}
String nextTarget = nextRefResourceType + "/EX" + nextRefIdPart;
nextRef.getResourceReference().setResource(null);
nextRef.getResourceReference().setReference(nextTarget);
if (checkedTargets.add(nextTarget) == false) {
continue;
}
boolean found = false;
for (int j = 0; j < resources.size(); j++) {
String candidateTarget = resources.get(j).getIdElement().getValue();
if (isNotBlank(nextTarget) && nextTarget.equals(candidateTarget)) {
ourLog.info("Reflexively adding resource {} to bundle as it is a reference target", nextTarget);
subResourceList.add(resources.remove(j));
found = true;
break;
}
}
}
} else {
if (ctx.getResourceDefinition(parsed).getName().equals("SearchParameter")) {
continue;
}
org.hl7.fhir.r4.model.Bundle.BundleEntryComponent entry = bundle.addEntry();
entry.getRequest().setMethod(org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST);
entry.setResource((org.hl7.fhir.r4.model.Resource) parsed);
}
if (subResourceList.size() < 10 && resources.size() > 0) {
subResourceList.add(resources.remove(0));
continue;
}
ourLog.info("About to upload {} examples in a transaction, {} remaining", subResourceList.size(), resources.size());
IVersionSpecificBundleFactory bundleFactory = ctx.newBundleFactory();
bundleFactory.initializeBundleFromResourceList(null, subResourceList, null, null, 0, BundleTypeEnum.TRANSACTION);
IBaseResource subBundle = bundleFactory.getResourceBundle();
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(subBundle);
ourLog.info("Final bundle: {}", FileUtils.byteCountToDisplaySize(encoded.length()));
if (targetServer.startsWith("file://")) {
String path = targetServer.substring("file://".length());
ourLog.info("Writing bundle to: {}", path);
File file = new File(path);
if (file.exists()) {
throw new Exception("File already exists: " + file.getAbsolutePath());
}
FileWriter w = new FileWriter(file, false);
w.append(encoded);
w.close();
} else {
ourLog.info("Uploading bundle to server: " + targetServer);
IGenericClient fhirClient = newClient(ctx, targetServer);
fhirClient.registerInterceptor(new GZipContentInterceptor());
long start = System.currentTimeMillis();
try {
fhirClient.transaction().withBundle(encoded).execute();
} catch (BaseServerResponseException e) {
ourLog.error("Failed to upload bundle:HTTP " + e.getStatusCode() + ": " + e.getMessage());
ourLog.error("Failing bundle: {}", encoded);
}
long delay = System.currentTimeMillis() - start;
ourLog.info("Finished uploading bundle to server (took {} ms)", delay);
}
subResourceList.clear();
}
return bundle;
}

View File

@ -1,19 +1,18 @@
package ca.uhn.fhir.cli;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.igpacks.parser.IgPackParserDstu3;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import parser.IgPackParserDstu3;
import parser.IgPackValidationSupportDstu3;
import java.io.File;
import java.io.FileInputStream;

View File

@ -4,7 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;

View File

@ -1,32 +1,87 @@
package ca.uhn.fhir.cli;
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import org.apache.commons.cli.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class ValidationDataUploader extends BaseCommand {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationDataUploader.class);
private ArrayList<IIdType> myExcludes = new ArrayList<>();
private void filterBundle(ca.uhn.fhir.model.dstu2.resource.Bundle theBundle) {
for (Iterator<Entry> iter = theBundle.getEntry().iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next().getResource();
for (IIdType nextExclude : myExcludes) {
if (nextExclude.hasResourceType() && nextExclude.toUnqualifiedVersionless().getValue().equals(next.getIdElement().toUnqualifiedVersionless().getValue())) {
iter.remove();
continue;
} else if (nextExclude.getIdPart().equals(next.getIdElement().getIdPart())) {
iter.remove();
continue;
}
}
}
}
private void filterBundle(org.hl7.fhir.dstu3.model.Bundle theBundle) {
for (Iterator<BundleEntryComponent> iter = theBundle.getEntry().iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next().getResource();
for (IIdType nextExclude : myExcludes) {
if (nextExclude.hasResourceType() && nextExclude.toUnqualifiedVersionless().getValue().equals(next.getIdElement().toUnqualifiedVersionless().getValue())) {
iter.remove();
continue;
} else if (nextExclude.getIdPart().equals(next.getIdElement().getIdPart())) {
iter.remove();
continue;
}
}
}
}
private void filterBundle(org.hl7.fhir.r4.model.Bundle theBundle) {
for (Iterator<org.hl7.fhir.r4.model.Bundle.BundleEntryComponent> iter = theBundle.getEntry().iterator(); iter.hasNext(); ) {
IBaseResource next = iter.next().getResource();
for (IIdType nextExclude : myExcludes) {
if (nextExclude.hasResourceType() && nextExclude.toUnqualifiedVersionless().getValue().equals(next.getIdElement().toUnqualifiedVersionless().getValue())) {
iter.remove();
continue;
} else if (nextExclude.getIdPart().equals(next.getIdElement().getIdPart())) {
iter.remove();
continue;
}
}
}
}
@Override
public String getCommandDescription() {
return "Uploads the conformance resources (StructureDefinition and ValueSet) from the official FHIR definitions.";
@ -43,11 +98,15 @@ public class ValidationDataUploader extends BaseCommand {
Option opt;
addFhirVersionOption(options);
opt = new Option("t", "target", true, "Base URL for the target server (e.g. \"http://example.com/fhir\")");
opt.setRequired(true);
options.addOption(opt);
opt = new Option("e", "exclude", true, "Exclude uploading the given resources, e.g. \"-e dicom-dcim,foo\"");
opt.setRequired(false);
options.addOption(opt);
return options;
}
@ -61,13 +120,26 @@ public class ValidationDataUploader extends BaseCommand {
}
FhirContext ctx = getSpecVersionContext(theCommandLine);
String exclude = theCommandLine.getOptionValue("e");
if (isNotBlank(exclude)) {
for (String next : exclude.split(",")) {
if (isNotBlank(next)) {
IIdType id = ctx.getVersion().newIdType();
id.setValue(next);
myExcludes.add(id);
}
}
}
if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU2) {
uploadDefinitionsDstu2(targetServer, ctx);
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU3){
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
uploadDefinitionsDstu3(targetServer, ctx);
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.R4){
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.R4) {
uploadDefinitionsR4(targetServer, ctx);
}
}
private void uploadDefinitionsDstu2(String targetServer, FhirContext ctx) throws CommandFailureException {
@ -79,7 +151,7 @@ public class ValidationDataUploader extends BaseCommand {
String vsContents;
try {
ctx.getVersion().getPathToSchemaDefinitions();
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/"+"valuesets.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/" + "valuesets.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
@ -91,14 +163,14 @@ public class ValidationDataUploader extends BaseCommand {
ValueSet next = (ValueSet) i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
ourLog.info("Uploading ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()});
client.update().resource(next).execute();
count++;
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/"+"v3-codesystems.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/" + "v3-codesystems.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
@ -110,14 +182,14 @@ public class ValidationDataUploader extends BaseCommand {
ValueSet next = (ValueSet) i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
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/instance/model/valueset/"+"v2-tables.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/" + "v2-tables.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
@ -128,7 +200,7 @@ public class ValidationDataUploader extends BaseCommand {
ValueSet next = (ValueSet) i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()});
client.update().resource(next).execute();
count++;
}
@ -138,7 +210,7 @@ public class ValidationDataUploader extends BaseCommand {
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
Resource[] mappingLocations;
try {
mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/"+"*.profile.xml");
mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/" + "*.profile.xml");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
@ -153,7 +225,7 @@ public class ValidationDataUploader extends BaseCommand {
}
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()});
try {
client.update().resource(next).execute();
} catch (Exception e) {
@ -178,14 +250,15 @@ public class ValidationDataUploader extends BaseCommand {
int count = 0;
org.hl7.fhir.dstu3.model.Bundle bundle;
String vsContents;
try {
ctx.getVersion().getPathToSchemaDefinitions();
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/"+"valuesets.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/" + "valuesets.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = ctx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
@ -194,8 +267,8 @@ public class ValidationDataUploader extends BaseCommand {
next.setId(next.getIdElement().toUnqualifiedVersionless());
int bytes = ctx.newXmlParser().encodeResourceToString(next).length();
ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[] { count, total, next.getIdElement().getValue(), bytes });
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());
@ -206,47 +279,53 @@ public class ValidationDataUploader extends BaseCommand {
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/"+"v3-codesystems.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/" + "v3-codesystems.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = ctx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
for (BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.dstu3.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();
ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()});
try {
client.update().resource(next).execute();
} catch (Exception e) {
ourLog.error("Failed to upload: {}", e.toString());
}
count++;
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/"+"v2-tables.xml"), "UTF-8");
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/valueset/" + "v2-tables.xml"), "UTF-8");
} catch (IOException e) {
throw new CommandFailureException(e.toString());
}
bundle = ctx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
for (BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.dstu3.model.Resource next = i.getResource();
if (next.getIdElement().isIdPartValidLong()) {
next.setIdElement(new IdType("v2-"+ next.getIdElement().getIdPart()));
next.setIdElement(new IdType("v2-" + next.getIdElement().getIdPart()));
}
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
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(ctx, client, "profiles-resources");
uploadDstu3Profiles(ctx, client, "profiles-types");
uploadDstu3Profiles(ctx, client, "profiles-others");
@ -270,11 +349,12 @@ public class ValidationDataUploader extends BaseCommand {
try {
theCtx.getVersion().getPathToSchemaDefinitions();
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/r4/model/valueset/"+"valuesets.xml"), "UTF-8");
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);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
@ -284,7 +364,7 @@ public class ValidationDataUploader extends BaseCommand {
int bytes = theCtx.newXmlParser().encodeResourceToString(next).length();
ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[] { count, total, next.getIdElement().getValue(), bytes });
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());
@ -295,40 +375,42 @@ public class ValidationDataUploader extends BaseCommand {
}
try {
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/r4/model/valueset/"+"v3-codesystems.xml"), "UTF-8");
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);
filterBundle(bundle);
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() });
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");
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);
filterBundle(bundle);
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.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() });
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()});
client.update().resource(next).execute();
count++;
}
@ -360,9 +442,10 @@ public class ValidationDataUploader extends BaseCommand {
}
bundle = ctx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
Collections.sort(bundle.getEntry(), new Comparator<BundleEntryComponent>() {
@Override
public int compare(BundleEntryComponent theO1, BundleEntryComponent theO2) {
@ -377,18 +460,19 @@ public class ValidationDataUploader extends BaseCommand {
}
// StructureDefinition, then OperationDefinition, then CompartmentDefinition
return theO2.getResource().getClass().getName().compareTo(theO1.getResource().getClass().getName());
}});
}
});
for (BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.dstu3.model.Resource next = i.getResource();
next.setId(next.getIdElement().toUnqualifiedVersionless());
if (next instanceof CapabilityStatement) {
continue;
}
ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[] { name, count, total, next.getIdElement().getValue() });
ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[]{name, count, total, next.getIdElement().getValue()});
client.update().resource(next).execute();
count++;
}
}
@ -406,6 +490,7 @@ public class ValidationDataUploader extends BaseCommand {
}
bundle = ctx.newXmlParser().parseResource(org.hl7.fhir.r4.model.Bundle.class, vsContents);
filterBundle(bundle);
total = bundle.getEntry().size();
count = 1;
@ -423,7 +508,8 @@ public class ValidationDataUploader extends BaseCommand {
}
// StructureDefinition, then OperationDefinition, then CompartmentDefinition
return theO2.getResource().getClass().getName().compareTo(theO1.getResource().getClass().getName());
}});
}
});
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent i : bundle.getEntry()) {
org.hl7.fhir.r4.model.Resource next = i.getResource();
@ -432,7 +518,7 @@ public class ValidationDataUploader extends BaseCommand {
continue;
}
ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[] { name, count, total, next.getIdElement().getValue() });
ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[]{name, count, total, next.getIdElement().getValue()});
client.update().resource(next).execute();
count++;

View File

@ -1,4 +1,4 @@
package parser;
package ca.uhn.fhir.igpacks.parser;
import ca.uhn.fhir.context.FhirContext;
@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.ImplementationGuide;
import org.hl7.fhir.instance.model.api.IBaseResource;

View File

@ -1,7 +1,7 @@
package parser;
package ca.uhn.fhir.igpacks.parser;
import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.StructureDefinition;

View File

@ -2,13 +2,12 @@ package ca.uhn.fhir.igpack.parser;
import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import ca.uhn.fhir.igpacks.parser.IgPackParserDstu3;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import parser.IgPackParserDstu3;
import static org.junit.Assert.*;

View File

@ -1,7 +1,7 @@
package ca.uhn.fhir.jpa.config.dstu3;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.utils.IResourceValidator.BestPracticeWarningLevel;
/*

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.dao.data;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceIndexedCompositeStringUnique;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

View File

@ -20,28 +20,39 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.*;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.instance.model.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.LogicUtil;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.IdType;
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.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
@ -50,6 +61,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
@Autowired
private ITermCodeSystemVersionDao myCsvDao;
@Autowired
private ITermCodeSystemDao myCsDao;
@Autowired
private IHapiTerminologySvc myTerminologySvc;
@ -115,7 +129,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
}
ourLog.info("Looking up {} / {}", system, code);
if (myValidationSupport.isCodeSystemSupported(getContext(), system)) {
ourLog.info("Code system {} is supported", system);
@ -133,7 +147,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
return retVal;
}
}
// HapiWorkerContext ctx = new HapiWorkerContext(getContext(), myValidationSupport);
// ValueSetExpander expander = ctx.getExpander();
// ValueSet source = new ValueSet();
@ -165,8 +179,21 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
}
@Override
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
super.preDelete(theResourceToDelete, theEntityToDelete);
String codeSystemUrl = theResourceToDelete.getUrl();
if (isNotBlank(codeSystemUrl)) {
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
if (persCs != null) {
myTerminologySvc.deleteCodeSystem(persCs);
}
}
}
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
ArrayList<TermConcept> retVal = new ArrayList<TermConcept>();
ArrayList<TermConcept> retVal = new ArrayList<>();
for (ConceptDefinitionComponent next : theConcept) {
if (isNotBlank(next.getCode())) {
@ -181,32 +208,35 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
return retVal;
}
@Override
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
CodeSystem cs = (CodeSystem) theResource;
if (cs != null && isNotBlank(cs.getUrl())) {
String codeSystemUrl = cs.getUrl();
if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
Long codeSystemResourcePid = retVal.getId();
if (retVal.getDeleted() != null) {
// deleting
} else if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
Long codeSystemResourcePid = retVal.getId();
TermCodeSystemVersion persCs = myCsvDao.findByCodeSystemResourceAndVersion(codeSystemResourcePid, retVal.getVersion());
if (persCs != null) {
ourLog.info("Code system version already exists in database");
} else {
persCs = new TermCodeSystemVersion();
persCs.setResource(retVal);
persCs.setResourceVersionId(retVal.getVersion());
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
myTerminologySvc.storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, persCs);
}
}

View File

@ -32,9 +32,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* 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.

View File

@ -27,8 +27,8 @@ import java.util.Collections;
import java.util.List;
import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
import org.hl7.fhir.dstu3.model.ValueSet.*;

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
/*
* #%L

View File

@ -31,7 +31,7 @@ import javax.measure.unit.Unit;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestSecurityComponent;
import org.hl7.fhir.dstu3.model.Enumeration;
@ -55,7 +55,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorDstu3.class);
@Autowired
private org.hl7.fhir.dstu3.hapi.validation.IValidationSupport myValidationSupport;
private org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport myValidationSupport;
/**
* Constructor
@ -690,7 +690,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
*/
@Override
protected List<Object> extractValues(String thePaths, IBaseResource theResource) {
IWorkerContext worker = new org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext(getContext(), myValidationSupport);
IWorkerContext worker = new org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
FHIRPathEngine fp = new FHIRPathEngine(worker);
List<Object> values = new ArrayList<Object>();
@ -736,7 +736,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
}
@VisibleForTesting
void setValidationSupportForTesting(org.hl7.fhir.dstu3.hapi.validation.IValidationSupport theValidationSupport) {
void setValidationSupportForTesting(org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport theValidationSupport) {
myValidationSupport = theValidationSupport;
}

View File

@ -20,28 +20,39 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.*;
import org.hl7.fhir.r4.hapi.ctx.ValidationSupportChain;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.instance.model.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.LogicUtil;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
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.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.r4.hapi.ctx.ValidationSupportChain;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.IdType;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
@ -49,10 +60,10 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
@Autowired
private ITermCodeSystemVersionDao myCsvDao;
@Autowired
private ITermCodeSystemDao myCsDao;
@Autowired
private IHapiTerminologySvc myTerminologySvc;
@Autowired
private ValidationSupportChain myValidationSupport;
@ -115,7 +126,7 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
}
ourLog.info("Looking up {} / {}", system, code);
if (myValidationSupport.isCodeSystemSupported(getContext(), system)) {
ourLog.info("Code system {} is supported", system);
@ -133,7 +144,7 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
return retVal;
}
}
// HapiWorkerContext ctx = new HapiWorkerContext(getContext(), myValidationSupport);
// ValueSetExpander expander = ctx.getExpander();
// ValueSet source = new ValueSet();
@ -165,6 +176,19 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
}
@Override
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
super.preDelete(theResourceToDelete, theEntityToDelete);
String codeSystemUrl = theResourceToDelete.getUrl();
if (isNotBlank(codeSystemUrl)) {
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
if (persCs != null) {
myTerminologySvc.deleteCodeSystem(persCs);
}
}
}
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
ArrayList<TermConcept> retVal = new ArrayList<TermConcept>();
@ -181,10 +205,10 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
return retVal;
}
@Override
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
CodeSystem cs = (CodeSystem) theResource;
@ -193,20 +217,20 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
String codeSystemUrl = cs.getUrl();
if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
Long codeSystemResourcePid = retVal.getId();
TermCodeSystemVersion persCs = myCsvDao.findByCodeSystemResourceAndVersion(codeSystemResourcePid, retVal.getVersion());
if (persCs != null) {
ourLog.info("Code system version already exists in database");
} else {
persCs = new TermCodeSystemVersion();
persCs.setResource(retVal);
persCs.setResourceVersionId(retVal.getVersion());
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
myTerminologySvc.storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, persCs);
}
}

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.entity;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.*;
import org.hl7.fhir.r4.model.Resource;

View File

@ -20,69 +20,59 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import javax.persistence.*;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
//@formatter:off
@Table(name="TRM_CODESYSTEM", uniqueConstraints= {
@UniqueConstraint(name="IDX_CS_CODESYSTEM", columnNames= {"CODE_SYSTEM_URI"})
@Table(name = "TRM_CODESYSTEM", uniqueConstraints = {
@UniqueConstraint(name = "IDX_CS_CODESYSTEM", columnNames = {"CODE_SYSTEM_URI"})
})
@Entity()
//@formatter:on
public class TermCodeSystem implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name="CODE_SYSTEM_URI", nullable=false)
@Column(name = "CODE_SYSTEM_URI", nullable = false)
private String myCodeSystemUri;
@OneToOne()
@JoinColumn(name="CURRENT_VERSION_PID", referencedColumnName="PID", nullable=true, foreignKey=@ForeignKey(name="FK_TRMCODESYSTEM_CURVER"))
@JoinColumn(name = "CURRENT_VERSION_PID", referencedColumnName = "PID", nullable = true, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_CURVER"))
private TermCodeSystemVersion myCurrentVersion;
@Id()
@SequenceGenerator(name = "SEQ_CODESYSTEM_PID", sequenceName = "SEQ_CODESYSTEM_PID")
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CODESYSTEM_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEM_PID")
@Column(name = "PID")
private Long myPid;
@OneToOne()
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey=@ForeignKey(name="FK_TRMCODESYSTEM_RES"))
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES"))
private ResourceTable myResource;
@Column(name = "RES_ID", insertable=false, updatable=false)
@Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid;
public String getCodeSystemUri() {
return myCodeSystemUri;
}
public TermCodeSystemVersion getCurrentVersion() {
return myCurrentVersion;
}
public ResourceTable getResource() {
return myResource;
}
public void setCodeSystemUri(String theCodeSystemUri) {
myCodeSystemUri = theCodeSystemUri;
}
public TermCodeSystemVersion getCurrentVersion() {
return myCurrentVersion;
}
public void setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
myCurrentVersion = theCurrentVersion;
}
public Long getPid() {
return myPid;
}
public ResourceTable getResource() {
return myResource;
}
public void setResource(ResourceTable theResource) {
myResource = theResource;
}

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.search;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import org.hl7.fhir.instance.model.api.IBaseReference;

View File

@ -618,4 +618,15 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
ourForceSaveDeferredAlwaysForUnitTest = theForceSaveDeferredAlwaysForUnitTest;
}
@Override
public void deleteCodeSystem(TermCodeSystem theCodeSystem) {
ourLog.info(" * Deleting code system {}", theCodeSystem.getPid());
for (TermCodeSystemVersion next : myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystem.getPid())) {
myConceptParentChildLinkDao.deleteByCodeSystemVersion(next.getPid());
myConceptDao.deleteByCodeSystemVersion(next.getPid());
}
myCodeSystemDao.delete(theCodeSystem.getPid());
}
}

View File

@ -20,13 +20,12 @@ package ca.uhn.fhir.jpa.term;
* #L%
*/
import java.util.List;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.hapi.validation.IValidationSupport;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import java.util.List;
public class HapiTerminologySvcDstu2 extends BaseHapiTerminologySvc {
@ -46,5 +45,4 @@ public class HapiTerminologySvcDstu2 extends BaseHapiTerminologySvc {
}
}

View File

@ -1,5 +1,40 @@
package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.query.dsl.BooleanJunction;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.ValueSet.*;
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@ -12,9 +47,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* 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.
@ -22,36 +57,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* limitations under the License.
* #L%
*/
import java.util.*;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.query.dsl.BooleanJunction;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.ValueSet.*;
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.UrlUtil;
public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements IValidationSupport, IHapiTerminologySvcDstu3 {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HapiTerminologySvcDstu3.class);

View File

@ -24,12 +24,15 @@ import java.util.List;
import java.util.Set;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.rest.api.server.RequestDetails;
public interface IHapiTerminologySvc {
void deleteCodeSystem(TermCodeSystem thePersCs);
Set<TermConcept> findCodesAbove(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);
Set<TermConcept> findCodesBelow(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.term;
* #L%
*/
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
public interface IHapiTerminologySvcDstu3 extends IHapiTerminologySvc, IValidationSupport {
// nothing

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.util;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class JpaConstants {
public static final String EXT_SP_UNIQUE = "http://hapifhir.io/fhir/StructureDefinition/sp-unique";

View File

@ -24,9 +24,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* 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.

View File

@ -24,9 +24,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* 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.

View File

@ -24,9 +24,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* 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.

View File

@ -12,7 +12,7 @@ import javax.persistence.EntityManager;
import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.*;

View File

@ -139,14 +139,6 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
// Search just got used so it shouldn't be deleted
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
assertNotNull(mySearchEntityDao.findByUuid(searchUuid3));
}
});
Thread.sleep(750);
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();

View File

@ -5,7 +5,7 @@ import static org.junit.Assert.fail;
import javax.persistence.EntityManager;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;

View File

@ -18,6 +18,7 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.orm.jpa.JpaSystemException;
import java.util.Collections;
@ -338,7 +339,7 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test
try {
myPatientDao.update(pt2);
fail();
} catch (JpaSystemException e) {
} catch (PreconditionFailedException e) {
// good
}

View File

@ -28,6 +28,21 @@ import ca.uhn.fhir.util.TestUtil;
public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3UpdateTest.class);
@Test
public void testReCreateMatchResource() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl("http://foo");
IIdType id = myCodeSystemDao.create(codeSystem).getId().toUnqualifiedVersionless();
myCodeSystemDao.delete(id);
codeSystem = new CodeSystem();
codeSystem.setUrl("http://foo");
myCodeSystemDao.update(codeSystem, "Patient?name=FAM").getId().toUnqualifiedVersionless();
}
@Test
public void testCreateAndUpdateWithoutRequest() throws Exception {
String methodName = "testUpdateByUrl";

View File

@ -9,7 +9,7 @@ import java.util.Set;
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.Observation;
import org.junit.AfterClass;
import org.junit.BeforeClass;

View File

@ -28,6 +28,21 @@ import ca.uhn.fhir.util.TestUtil;
public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UpdateTest.class);
@Test
public void testReCreateMatchResource() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl("http://foo");
IIdType id = myCodeSystemDao.create(codeSystem).getId().toUnqualifiedVersionless();
myCodeSystemDao.delete(id);
codeSystem = new CodeSystem();
codeSystem.setUrl("http://foo");
myCodeSystemDao.update(codeSystem, "Patient?name=FAM").getId().toUnqualifiedVersionless();
}
@Test
public void testCreateAndUpdateWithoutRequest() throws Exception {
String methodName = "testUpdateByUrl";

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.provider.r4.ResourceProviderInterceptorR4Test;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Patient;
@ -114,12 +115,7 @@ public class ResourceProviderInterceptorDstu2Test extends BaseResourceProviderDs
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(myDaoInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
assertEquals(RestOperationTypeEnum.CREATE, opTypeCaptor.getValue());
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
ResourceProviderInterceptorR4Test.verifyDaoInterceptor(myDaoInterceptor);
}
@Test

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.provider.r4.ResourceProviderInterceptorR4Test;
import ca.uhn.fhir.model.dstu2.resource.Conformance;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.Constants;
@ -117,12 +118,7 @@ public class ResourceProviderInterceptorDstu3Test extends BaseResourceProviderDs
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(myDaoInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
assertEquals(RestOperationTypeEnum.CREATE, opTypeCaptor.getValue());
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
ResourceProviderInterceptorR4Test.verifyDaoInterceptor(myDaoInterceptor);
}
@Test

View File

@ -1,29 +1,5 @@
package ca.uhn.fhir.jpa.provider.r4;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
@ -33,6 +9,35 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Reference;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Test {
@ -112,66 +117,15 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(myDaoInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
assertEquals(RestOperationTypeEnum.CREATE, opTypeCaptor.getValue());
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
}
@Test
public void testCreateResourceWithVersionedReference() throws IOException, ServletException {
String methodName = "testCreateResourceWithVersionedReference";
Organization org = new Organization();
org.setName("orgName");
IIdType orgId = ourClient.create().resource(org).execute().getId().toUnqualified();
assertNotNull(orgId.getVersionIdPartAsLong());
resetServerInterceptor();
Patient pt = new Patient();
pt.addName().setFamily(methodName);
pt.setManagingOrganization(new Reference(orgId));
IParser parser = myFhirCtx.newXmlParser();
parser.setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization");
parser.setPrettyPrint(true);
String resource = parser.encodeResourceToString(pt);
ourLog.info(resource);
verify(myServerInterceptor, times(0)).incomingRequestPreHandled(any(RestOperationTypeEnum.class), any(ActionRequestDetails.class));
verify(myDaoInterceptor, times(0)).incomingRequestPreHandled(any(RestOperationTypeEnum.class), any(ActionRequestDetails.class));
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info("Response was: {}", resp);
assertEquals(201, response.getStatusLine().getStatusCode());
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
} finally {
response.close();
}
ArgumentCaptor<ActionRequestDetails> ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
ArgumentCaptor<RestOperationTypeEnum> opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(myServerInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
assertEquals(RestOperationTypeEnum.CREATE, opTypeCaptor.getValue());
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
Patient patient;
patient = (Patient) ardCaptor.getAllValues().get(0).getResource();
assertEquals(orgId.getValue(), patient.getManagingOrganization().getReference());
ResourceProviderInterceptorR4Test.verifyDaoInterceptor(myDaoInterceptor);
}
/*
* This is a weird way of verifying, but because this class
* is a child of a superclass that has other test children
* it's possible that other tests are hitting the server
* at the same time
*/
@Test
public void testCreateResourceInTransaction() throws IOException {
String methodName = "testCreateResourceInTransaction";
@ -238,9 +192,80 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
}
@Test
public void testCreateResourceWithVersionedReference() throws IOException, ServletException {
String methodName = "testCreateResourceWithVersionedReference";
Organization org = new Organization();
org.setName("orgName");
IIdType orgId = ourClient.create().resource(org).execute().getId().toUnqualified();
assertNotNull(orgId.getVersionIdPartAsLong());
resetServerInterceptor();
Patient pt = new Patient();
pt.addName().setFamily(methodName);
pt.setManagingOrganization(new Reference(orgId));
IParser parser = myFhirCtx.newXmlParser();
parser.setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization");
parser.setPrettyPrint(true);
String resource = parser.encodeResourceToString(pt);
ourLog.info(resource);
verify(myServerInterceptor, times(0)).incomingRequestPreHandled(any(RestOperationTypeEnum.class), any(ActionRequestDetails.class));
verify(myDaoInterceptor, times(0)).incomingRequestPreHandled(any(RestOperationTypeEnum.class), any(ActionRequestDetails.class));
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info("Response was: {}", resp);
assertEquals(201, response.getStatusLine().getStatusCode());
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
} finally {
response.close();
}
ArgumentCaptor<ActionRequestDetails> ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
ArgumentCaptor<RestOperationTypeEnum> opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(myServerInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
assertEquals(RestOperationTypeEnum.CREATE, opTypeCaptor.getValue());
assertEquals("Patient", ardCaptor.getValue().getResourceType());
assertNotNull(ardCaptor.getValue().getResource());
Patient patient;
patient = (Patient) ardCaptor.getAllValues().get(0).getResource();
assertEquals(orgId.getValue(), patient.getManagingOrganization().getReference());
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
public static void verifyDaoInterceptor(IServerInterceptor theDaoInterceptor) {
ArgumentCaptor<ActionRequestDetails> ardCaptor;
ArgumentCaptor<RestOperationTypeEnum> opTypeCaptor;
ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class);
opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
verify(theDaoInterceptor, atLeast(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture());
boolean good = false;
for (int i = 0; i < opTypeCaptor.getAllValues().size(); i++) {
if (RestOperationTypeEnum.CREATE.equals(opTypeCaptor.getAllValues().get(i))) {
if ("Patient".equals(ardCaptor.getValue().getResourceType())) {
if (ardCaptor.getValue().getResource() != null) {
good = true;
}
}
}
}
assertTrue(good);
}
}

View File

@ -165,6 +165,41 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
return ids;
}
@Test
public void testUpdateThatCreatesReturnsHttp201() throws IOException {
Patient p = new Patient();
p.setId("A");
p.setActive(true);
String encoded = myFhirCtx.newJsonParser().encodeResourceToString(p);
HttpPut put = new HttpPut(ourServerBase + "/Patient/A");
put.setEntity(new StringEntity(encoded, "application/fhir+json", "UTF-8"));
CloseableHttpResponse response = ourHttpClient.execute(put);
try {
assertEquals(201, response.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(response);
}
p = new Patient();
p.setId("A");
p.setActive(false);
encoded = myFhirCtx.newJsonParser().encodeResourceToString(p);
put = new HttpPut(ourServerBase + "/Patient/A");
put.setEntity(new StringEntity(encoded, "application/fhir+json", "UTF-8"));
response = ourHttpClient.execute(put);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(response);
}
}
// Y
@Test
public void testBundleCreate() throws Exception {

View File

@ -20,24 +20,25 @@ package org.hl7.fhir.dstu3.hapi.ctx;
* #L%
*/
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.hapi.fluentpath.FluentPathDstu3;
import org.hl7.fhir.dstu3.hapi.rest.server.Dstu3BundleFactory;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.fluentpath.IFluentPath;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
import ca.uhn.fhir.util.ReflectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.hapi.fluentpath.FluentPathDstu3;
import org.hl7.fhir.dstu3.hapi.rest.server.Dstu3BundleFactory;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.*;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class FhirDstu3 implements IFhirVersion {
@ -50,7 +51,12 @@ public class FhirDstu3 implements IFhirVersion {
@Override
public IContextValidationSupport<?, ?, ?, ?, ?, ?> createValidationSupport() {
return new DefaultProfileValidationSupport();
String className = "org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport";
try {
return (IContextValidationSupport<?, ?, ?, ?, ?, ?>) Class.forName(className).newInstance();
} catch (Exception theE) {
throw new ConfigurationException(className + " is not on classpath. Make sure that hapi-fhir-validation-VERSION.jar is available.");
}
}
@Override

View File

@ -1,34 +1,15 @@
package org.hl7.fhir.dstu3.hapi.validation;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
package org.hl7.fhir.dstu3.hapi.ctx;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.CoverageIgnore;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.formats.IParser;
import org.hl7.fhir.dstu3.formats.ParserType;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.ExpansionProfile;
import org.hl7.fhir.dstu3.model.MetadataResource;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.dstu3.model.ResourceType;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
@ -42,10 +23,10 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.CoverageIgnore;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander, ValueSetExpanderFactory {
private final FhirContext myCtx;
@ -196,7 +177,7 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay) {
CodeValidationResult result = myValidationSupport.validateCode(myCtx, theSystem, theCode, theDisplay);
IValidationSupport.CodeValidationResult result = myValidationSupport.validateCode(myCtx, theSystem, theCode, theDisplay);
if (result == null) {
return null;
}
@ -359,4 +340,4 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
throw new UnsupportedOperationException();
}
}
}

View File

@ -1,4 +1,4 @@
package org.hl7.fhir.dstu3.hapi.validation;
package org.hl7.fhir.dstu3.hapi.ctx;
import java.util.List;

View File

@ -1,17 +1,16 @@
package org.hl7.fhir.dstu3.hapi.fluentpath;
import java.util.List;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
import ca.uhn.fhir.fluentpath.IFluentPath;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.Base;
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBase;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
import ca.uhn.fhir.fluentpath.IFluentPath;
import java.util.List;
public class FluentPathDstu3 implements IFluentPath {

View File

@ -11,9 +11,8 @@ import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.dstu3.model.Resource;
@ -30,15 +29,6 @@ public class GraphQLProviderDstu3 {
private Logger ourLog = LoggerFactory.getLogger(GraphQLProviderDstu3.class);
private IGraphQLStorageServices<Resource, Reference, Bundle> myStorageServices;
/**
* Constructor which uses a default context and validation support object
*
* @param theStorageServices The storage services (this object will be used to retrieve various resources as required by the GraphQL engine)
*/
public GraphQLProviderDstu3(IGraphQLStorageServices<Resource, Reference, Bundle> theStorageServices) {
this(FhirContext.forDstu3(), new DefaultProfileValidationSupport(), theStorageServices);
}
/**
* Constructor which uses the given worker context
*

View File

@ -309,8 +309,10 @@ public class GraphQLEngine {
}
if (fp.length() == 0)
for (Base v : values) {
if (passesExtensionMode(v, extensionMode))
result.add(v);
if (v != null) {
if (passesExtensionMode(v, extensionMode))
result.add(v);
}
} else {
FHIRPathEngine fpe = new FHIRPathEngine(this.context);
ExpressionNode node = fpe.parse(fp.toString().substring(5));
@ -416,6 +418,8 @@ public class GraphQLEngine {
if (prop == null) {
if ((sel.getField().getName().equals("resourceType") && source instanceof Resource))
target.addField("resourceType", false).addValue(new StringValue(source.fhirType()));
else if ((sel.getField().getName().equals("id") && source instanceof Resource))
target.addField("id", false).addValue(new StringValue(((Resource) source).getIdElement().getIdPart()));
else if ((sel.getField().getName().equals("resource") && source.fhirType().equals("Reference")))
processReference(context, source, sel.getField(), target);
else if (isResourceName(sel.getField().getName(), "List") && (source instanceof Resource))

View File

@ -1,446 +0,0 @@
package org.hl7.fhir.dstu3.validation;
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import java.text.MessageFormat;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
public class BaseValidator {
protected Source source;
/**
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean fail(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, line, col, path, msg, IssueSeverity.FATAL));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass) {
String path = toPath(pathParts);
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.FATAL));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
errors.add(new ValidationMessage(source, type, -1, -1, path, formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean fail(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.FATAL));
}
return thePass;
}
private String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
message = MessageFormat.format(theMessage, theMessageArguments);
} else {
message = theMessage;
}
return message;
}
protected boolean grammarWord(String w) {
return w.equals("and") || w.equals("or") || w.equals("a") || w.equals("the") || w.equals("for") || w.equals("this") || w.equals("that") || w.equals("of");
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, line, col, path, msg, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, line, col, path, message, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean hint(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, message, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean hint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean rule(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, line, col, path, message, IssueSeverity.ERROR));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean rule(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass) {
String path = toPath(pathParts);
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.ERROR));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean rule(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, message, IssueSeverity.ERROR));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.ERROR));
}
return thePass;
}
static public boolean rule(List<ValidationMessage> errors, Source source, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.ERROR));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, IssueSeverity.ERROR));
}
return thePass;
}
protected String splitByCamelCase(String s) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isUpperCase(c) && !(i == 0 || Character.isUpperCase(s.charAt(i-1))))
b.append(' ');
b.append(c);
}
return b.toString();
}
protected String stripPunctuation(String s, boolean numbers) {
StringBuilder b = new StringBuilder();
for (char c : s.toCharArray()) {
int t = Character.getType(c);
if (t == Character.UPPERCASE_LETTER || t == Character.LOWERCASE_LETTER || t == Character.TITLECASE_LETTER || t == Character.MODIFIER_LETTER || t == Character.OTHER_LETTER || (t == Character.DECIMAL_DIGIT_NUMBER && numbers) || (t == Character.LETTER_NUMBER && numbers) || c == ' ')
b.append(c);
}
return b.toString();
}
private String toPath(List<String> pathParts) {
if (pathParts == null || pathParts.isEmpty()) {
return "";
}
return "//" + StringUtils.join(pathParts, '/');
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(source, type, line, col, path, msg, IssueSeverity.WARNING));
}
return thePass;
}
protected boolean warningOrError(boolean isError, List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(source, type, line, col, path, msg, isError ? IssueSeverity.ERROR : IssueSeverity.WARNING));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, message, IssueSeverity.WARNING));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.WARNING));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, IssueSeverity.WARNING));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass) {
msg = formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, IssueSeverity.WARNING));
}
return thePass;
}
//---------
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(source, type, line, col, path, msg, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
String message = formatMessage(theMessage, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, message, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, IssueSeverity.INFORMATION));
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass) {
msg = formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, IssueSeverity.INFORMATION));
}
return thePass;
}
}

View File

@ -1,23 +0,0 @@
package org.hl7.fhir.dstu3.validation;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
/**
* Placeholder class - Do not use
*/
class ValidationEngine {
private ValidationEngine() {
}
public IWorkerContext getContext() {
return null;
}
public FHIRPathEngine getFpe() {
return null;
}
}

View File

@ -1,66 +0,0 @@
package org.hl7.fhir.dstu3.validation;
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import java.util.List;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class ValidationErrorHandler implements ErrorHandler {
private List<ValidationMessage> outputs;
private String path;
public ValidationErrorHandler(List<ValidationMessage> outputs, String path) {
this.outputs = outputs;
this.path = path;
}
@Override
public void error(SAXParseException arg0) throws SAXException {
outputs.add(new ValidationMessage(Source.Schema, IssueType.INVALID, arg0.getLineNumber(), arg0.getColumnNumber(), path, arg0.getMessage(), IssueSeverity.ERROR));
}
@Override
public void fatalError(SAXParseException arg0) throws SAXException {
outputs.add(new ValidationMessage(Source.Schema, IssueType.INVALID, arg0.getLineNumber(), arg0.getColumnNumber(), path, arg0.getMessage(), IssueSeverity.FATAL));
}
@Override
public void warning(SAXParseException arg0) throws SAXException {
outputs.add(new ValidationMessage(Source.Schema, IssueType.INVALID, arg0.getLineNumber(), arg0.getColumnNumber(), path, arg0.getMessage(), IssueSeverity.WARNING));
}
}

View File

@ -1,59 +1,5 @@
package ca.uhn.fhir.parser;
import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Address.AddressUse;
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.CapabilityStatement.UnknownContentCode;
import org.hl7.fhir.dstu3.model.Condition.ConditionVerificationStatus;
import org.hl7.fhir.dstu3.model.Enumeration;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.Identifier.IdentifierUse;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import com.google.common.base.Charsets;
import com.google.common.collect.Sets;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
@ -62,8 +8,47 @@ import ca.uhn.fhir.parser.XmlParserDstu3Test.TestPatientFor327;
import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType;
import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.*;
import net.sf.json.*;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import com.google.common.base.Charsets;
import com.google.common.collect.Sets;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.dstu3.model.Address.AddressUse;
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.CapabilityStatement.UnknownContentCode;
import org.hl7.fhir.dstu3.model.Condition.ConditionVerificationStatus;
import org.hl7.fhir.dstu3.model.Enumeration;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.Identifier.IdentifierUse;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.*;
public class JsonParserDstu3Test {
private static FhirContext ourCtx = FhirContext.forDstu3();
@ -74,77 +59,6 @@ public class JsonParserDstu3Test {
ourCtx.setNarrativeGenerator(null);
}
@Test
public void testActivityDefinitionElementsOrder() throws Exception {
final String origContent = "{\"resourceType\":\"ActivityDefinition\",\"id\":\"x1\",\"url\":\"http://testing.org\",\"status\":\"draft\",\"timingDateTime\":\"2011-02-03\"}";
final IParser parser = ourCtx.newJsonParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ActivityDefinition fhirObj = parser.parseResource(ActivityDefinition.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@Test
public void testConceptMapElementsOrder() throws Exception {
final String origContent = "{\"resourceType\":\"ConceptMap\",\"id\":\"x1\",\"url\":\"http://testing.org\",\"status\":\"draft\",\"sourceUri\":\"http://y1\"}";
final IParser parser = ourCtx.newJsonParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ConceptMap fhirObj = parser.parseResource(ConceptMap.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
/**
* See #563

View File

@ -32,8 +32,6 @@ import org.apache.commons.lang.StringUtils;
import org.hamcrest.collection.IsEmptyCollection;
import org.hamcrest.core.StringContains;
import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Address.AddressUse;
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
@ -142,80 +140,6 @@ public class XmlParserDstu3Test {
}
/**
* See #683
*/
@Test
public void testChildOrderWithChoiceType() throws Exception {
final String origContent = "<ActivityDefinition xmlns=\"http://hl7.org/fhir\"><id value=\"x1\"/><url value=\"http://testing.org\"/><status value=\"draft\"/><timingDateTime value=\"2011-02-03\"/></ActivityDefinition>";
final IParser parser = ourCtx.newXmlParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ActivityDefinition fhirObj = parser.parseResource(ActivityDefinition.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@Test
public void testConceptMapElementsOrder() throws Exception {
final String origContent = "<ConceptMap xmlns=\"http://hl7.org/fhir\"><id value=\"x1\"/><url value=\"http://testing.org\"/><status value=\"draft\"/><sourceUri value=\"http://url1\"/></ConceptMap>";
final IParser parser = ourCtx.newXmlParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ConceptMap fhirObj = parser.parseResource(ConceptMap.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@Test
public void testContainedResourceInExtensionUndeclared() {

View File

@ -173,6 +173,10 @@
<artifactId>phloc-commons</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<reporting>

View File

@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;

View File

@ -7,6 +7,8 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.dstu3.utils.IResourceValidator.BestPracticeWarningLevel;

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.dstu3.hapi.validation;
import ca.uhn.fhir.context.FhirContext;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.MetadataResource;
import org.hl7.fhir.dstu3.model.StructureDefinition;

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.dstu3.hapi.validation;
import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;

View File

@ -1,18 +1,17 @@
package ca.uhn.fhir.fluentpath;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import java.util.List;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.HumanName;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.StringType;
import org.junit.AfterClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
public class FluentPathTest {

View File

@ -9,6 +9,7 @@ import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
@ -18,23 +19,26 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.Matchers;
import org.hl7.fhir.dstu3.hapi.rest.server.GraphQLProviderDstu3;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.dstu3.hapi.rest.server.GraphQLProviderDstu3;
import org.hl7.fhir.utilities.graphql.Argument;
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
import org.hl7.fhir.utilities.graphql.ReferenceResolution;
import org.junit.*;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.*;
public class GraphQLDstu3ProviderTest {
@ -55,6 +59,8 @@ public class GraphQLDstu3ProviderTest {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
servlet.setDefaultResponseEncoding(EncodingEnum.JSON);
@ -62,7 +68,7 @@ public class GraphQLDstu3ProviderTest {
servlet.registerProvider(new DummyPatientResourceProvider());
MyStorageServices storageServices = new MyStorageServices();
servlet.registerProvider(new GraphQLProviderDstu3(storageServices));
servlet.registerProvider(new GraphQLProviderDstu3(ourCtx, new DefaultProfileValidationSupport(), storageServices));
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
@ -93,13 +99,13 @@ public class GraphQLDstu3ProviderTest {
assertEquals("{\n" +
" \"name\":[{\n" +
" \"family\":\"FAMILY\",\n" +
" \"family\":[\"FAMILY\"],\n" +
" \"given\":[\"GIVEN1\",\"GIVEN2\"]\n" +
" },{\n" +
" \"given\":[\"GivenOnly1\",\"GivenOnly2\"]\n" +
" }]\n" +
"}", responseContent);
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), startsWith("application/json"));
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), Matchers.startsWith("application/json"));
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
@ -108,7 +114,7 @@ public class GraphQLDstu3ProviderTest {
}
@Test
@Ignore
@org.junit.Ignore
public void testGraphSystemInstance() throws Exception {
String query = "{Patient(id:123){id,name{given,family}}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape(query));
@ -122,13 +128,13 @@ public class GraphQLDstu3ProviderTest {
" \"Patient\":{\n" +
" \"name\":[{\n" +
" \"given\":[\"GIVEN1\",\"GIVEN2\"],\n" +
" \"family\":\"FAMILY\"\n" +
" \"family\":[\"FAMILY\"]\n" +
" },{\n" +
" \"given\":[\"GivenOnly1\",\"GivenOnly2\"]\n" +
" }]\n" +
" }\n" +
"}", responseContent);
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), startsWith("application/json"));
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), Matchers.startsWith("application/json"));
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
@ -150,7 +156,7 @@ public class GraphQLDstu3ProviderTest {
assertEquals("{\n" +
" \"PatientList\":[{\n" +
" \"name\":[{\n" +
" \"family\":\"pet\",\n" +
" \"family\":[\"pet\"],\n" +
" \"given\":[\"GIVEN1\",\"GIVEN2\"]\n" +
" },{\n" +
" \"given\":[\"GivenOnly1\",\"GivenOnly2\"]\n" +
@ -161,7 +167,7 @@ public class GraphQLDstu3ProviderTest {
" }]\n" +
" }]\n" +
"}", responseContent);
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), startsWith("application/json"));
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), Matchers.startsWith("application/json"));
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
@ -183,10 +189,10 @@ public class GraphQLDstu3ProviderTest {
assertEquals("{\n" +
" \"name\":[{\n" +
" \"given\":[\"GIVEN1\",\"GIVEN2\"],\n" +
" \"family\":\"FAMILY\"\n" +
" \"family\":[\"FAMILY\"]\n" +
" }]\n" +
"}", responseContent);
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), startsWith("application/json"));
assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), Matchers.startsWith("application/json"));
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());

View File

@ -1,6 +1,5 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@ -21,6 +20,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.Matchers;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.IdType;
@ -95,8 +95,8 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
assertThat(responseContent, not(containsString("<severity value=\"error\"/>")));
assertThat(status.toString(), Matchers.containsString("X-FHIR-Request-Validation"));
assertThat(responseContent, Matchers.not(Matchers.containsString("<severity value=\"error\"/>")));
}
@Test
@ -121,8 +121,8 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
assertThat(responseContent, containsString("\"severity\":\"error\""));
assertThat(status.toString(), Matchers.containsString("X-FHIR-Request-Validation"));
assertThat(responseContent, Matchers.containsString("\"severity\":\"error\""));
}
@Test
@ -144,7 +144,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
}
@Test
@ -169,7 +169,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), (containsString("X-FHIR-Request-Validation: NO ISSUES")));
assertThat(status.toString(), (Matchers.containsString("X-FHIR-Request-Validation: NO ISSUES")));
}
@Test
@ -197,7 +197,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
assertThat(status.toString(), Matchers.containsString("X-FHIR-Request-Validation"));
}
@Test
@ -222,7 +222,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
assertThat(status.toString(), Matchers.containsString("X-FHIR-Request-Validation"));
}
@Test
@ -249,7 +249,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation: {\"resourceType\":\"OperationOutcome"));
assertThat(status.toString(), Matchers.containsString("X-FHIR-Request-Validation: {\"resourceType\":\"OperationOutcome"));
}
@ -280,7 +280,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<diagnostics value=\"java.lang.NullPointerException\"/>"));
assertThat(responseContent, Matchers.containsString("<diagnostics value=\"java.lang.NullPointerException\"/>"));
}
@SuppressWarnings("unchecked")
@ -310,7 +310,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
}
@SuppressWarnings("unchecked")
@ -340,7 +340,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<diagnostics value=\"FOO\"/>"));
assertThat(responseContent, Matchers.containsString("<diagnostics value=\"FOO\"/>"));
}
@SuppressWarnings("unchecked")
@ -370,7 +370,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
}
@Test
@ -392,7 +392,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
}
/**
@ -410,7 +410,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
assertEquals(204, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
} finally {
IOUtils.closeQuietly(status);
}
@ -434,7 +434,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("CapabilityStatement"));
assertThat(responseContent, Matchers.containsString("CapabilityStatement"));
}
@Test
@ -450,7 +450,7 @@ public class RequestValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Request-Validation")));
assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Request-Validation")));
assertEquals(true, ourLastRequestWasSearch);
}

View File

@ -1,9 +1,6 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@ -16,26 +13,19 @@ import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.Matchers;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.Identifier.IdentifierUse;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.*;
import org.mockito.Mockito;
import ca.uhn.fhir.context.FhirContext;
@ -107,8 +97,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<diagnostics value=\"java.lang.NullPointerException\"/>"));
Assert.assertEquals(500, status.getStatusLine().getStatusCode());
Assert.assertThat(responseContent, Matchers.containsString("<diagnostics value=\"java.lang.NullPointerException\"/>"));
}
@SuppressWarnings("unchecked")
@ -137,8 +127,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
}
@SuppressWarnings("unchecked")
@ -167,8 +157,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<diagnostics value=\"FOO\"/>"));
Assert.assertEquals(500, status.getStatusLine().getStatusCode());
Assert.assertThat(responseContent, Matchers.containsString("<diagnostics value=\"FOO\"/>"));
}
@SuppressWarnings("unchecked")
@ -197,8 +187,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
}
@ -216,8 +206,8 @@ public class ResponseValidatingInterceptorDstu3Test {
try {
ourLog.info("Response was:\n{}", status);
assertEquals(204, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(204, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
} finally {
IOUtils.closeQuietly(status);
}
@ -249,9 +239,9 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), endsWith("..."));
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), startsWith("{\"resourceType\":\"OperationOutcome\""));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), Matchers.endsWith("..."));
Assert.assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), Matchers.startsWith("{\"resourceType\":\"OperationOutcome\""));
}
{
myInterceptor.setMaximumHeaderLength(100);
@ -263,9 +253,9 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), endsWith("..."));
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), startsWith("{\"resourceType\":\"OperationOutcome\""));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), Matchers.endsWith("..."));
Assert.assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), Matchers.startsWith("{\"resourceType\":\"OperationOutcome\""));
}
}
@ -287,8 +277,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), (containsString(
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), (Matchers.containsString(
"X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}")));
}
@ -314,9 +304,9 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Response-Validation"));
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
Assert.assertEquals(422, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.containsString("X-FHIR-Response-Validation"));
Assert.assertThat(responseContent, Matchers.containsString("<severity value=\"error\"/>"));
}
@Test
@ -336,8 +326,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
}
@Test
@ -360,8 +350,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), (containsString("X-FHIR-Response-Validation: NO ISSUES")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), (Matchers.containsString("X-FHIR-Response-Validation: NO ISSUES")));
}
@Test
@ -386,8 +376,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Response-Validation"));
Assert.assertEquals(422, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.containsString("X-FHIR-Response-Validation"));
}
/**
@ -412,8 +402,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Response-Validation"));
Assert.assertEquals(422, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.containsString("X-FHIR-Response-Validation"));
}
@Test
@ -433,8 +423,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.trace("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
}
@Test
@ -453,8 +443,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), Matchers.not(Matchers.containsString("X-FHIR-Response-Validation")));
}
@Test
@ -474,8 +464,8 @@ public class ResponseValidatingInterceptorDstu3Test {
ourLog.info("Response was:\n{}", status);
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(status.toString(), (containsString("X-FHIR-Response-Validation")));
Assert.assertEquals(200, status.getStatusLine().getStatusCode());
Assert.assertThat(status.toString(), (Matchers.containsString("X-FHIR-Response-Validation")));
}
@AfterClass

View File

@ -0,0 +1,174 @@
package ca.uhn.fhir.validation;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.ActivityDefinition;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ParserWithValidationDstu3Test {
private static final Logger ourLog = LoggerFactory.getLogger(ParserWithValidationDstu3Test.class);
private static FhirContext ourCtx = FhirContext.forDstu3();
@Test
public void testActivityDefinitionElementsOrder() throws Exception {
final String origContent = "{\"resourceType\":\"ActivityDefinition\",\"id\":\"x1\",\"url\":\"http://testing.org\",\"status\":\"draft\",\"timingDateTime\":\"2011-02-03\"}";
final IParser parser = ourCtx.newJsonParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ActivityDefinition fhirObj = parser.parseResource(ActivityDefinition.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
/**
* See #683
*/
@Test
public void testChildOrderWithChoiceTypeXml() throws Exception {
final String origContent = "<ActivityDefinition xmlns=\"http://hl7.org/fhir\"><id value=\"x1\"/><url value=\"http://testing.org\"/><status value=\"draft\"/><timingDateTime value=\"2011-02-03\"/></ActivityDefinition>";
final IParser parser = ourCtx.newXmlParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ActivityDefinition fhirObj = parser.parseResource(ActivityDefinition.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@Test
public void testConceptMapElementsOrder() throws Exception {
final String origContent = "{\"resourceType\":\"ConceptMap\",\"id\":\"x1\",\"url\":\"http://testing.org\",\"status\":\"draft\",\"sourceUri\":\"http://y1\"}";
final IParser parser = ourCtx.newJsonParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ConceptMap fhirObj = parser.parseResource(ConceptMap.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@Test
public void testConceptMapElementsOrderXml() throws Exception {
final String origContent = "<ConceptMap xmlns=\"http://hl7.org/fhir\"><id value=\"x1\"/><url value=\"http://testing.org\"/><status value=\"draft\"/><sourceUri value=\"http://url1\"/></ConceptMap>";
final IParser parser = ourCtx.newXmlParser();
DefaultProfileValidationSupport validationSupport = new DefaultProfileValidationSupport();
// verify that InstanceValidator likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, origContent);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
ConceptMap fhirObj = parser.parseResource(ConceptMap.class, origContent);
String content = parser.encodeResourceToString(fhirObj);
ourLog.info("Serialized form: {}", content);
// verify that InstanceValidator still likes the format
{
IValidationContext<IBaseResource> validationCtx = ValidationContext.forText(ourCtx, content);
new FhirInstanceValidator(validationSupport).validateResource(validationCtx);
ValidationResult result = validationCtx.toResult();
for (SingleValidationMessage msg : result.getMessages()) {
ourLog.info("{}", msg);
}
Assert.assertEquals(0, result.getMessages().size());
}
// verify that the original and newly serialized match
Assert.assertEquals(origContent, content);
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
}

View File

@ -16,9 +16,9 @@ import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;

View File

@ -3,8 +3,8 @@ package org.hl7.fhir.dstu3.elementmodel;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.model.ElementDefinition;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.exceptions.DefinitionException;
@ -15,13 +15,12 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.*;
/**
* Created by axemj on 14/07/2017.
*/
public class PropertyTest {
public class PropertyDstu3Test {
private static final FhirContext ourCtx = FhirContext.forDstu3();
private Property property;

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.dstu3.hapi.validation;
import static org.junit.Assert.*;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.junit.AfterClass;
import org.junit.Test;

View File

@ -1,95 +1,195 @@
package ca.uhn.fhir.validation;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.GZIPInputStream;
package org.hl7.fhir.dstu3.hapi.validation;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhir.validation.SingleValidationMessage;
import ca.uhn.fhir.validation.ValidationResult;
import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.model.Base;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.ContactPoint;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.RelatedPerson;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.*;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.zip.GZIPInputStream;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class FhirInstanceValidatorDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorDstu3Test.class);
private static DefaultProfileValidationSupport myDefaultValidationSupport = new DefaultProfileValidationSupport();
private static FhirContext ourCtx = FhirContext.forDstu3();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorDstu3Test.class);
private FhirInstanceValidator myInstanceVal;
private IValidationSupport myMockSupport;
private Map<String, ValueSetExpansionComponent> mySupportedCodeSystemsForExpansion;
private FhirValidator myVal;
private ArrayList<String> myValidConcepts;
private Set<String> myValidSystems = new HashSet<String>();
@Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
ourLog.info("Starting test: " + description.getMethodName());
}
};
private FhirInstanceValidator myInstanceVal;
private IValidationSupport myMockSupport;
private Map<String, ValueSetExpansionComponent> mySupportedCodeSystemsForExpansion;
private FhirValidator myVal;
private ArrayList<String> myValidConcepts;
private Set<String> myValidSystems = new HashSet<String>();
private void addValidConcept(String theSystem, String theCode) {
myValidSystems.add(theSystem);
myValidConcepts.add(theSystem + "___" + theCode);
}
@SuppressWarnings("unchecked")
@Before
public void before() {
myVal = ourCtx.newValidator();
myVal.setValidateAgainstStandardSchema(false);
myVal.setValidateAgainstStandardSchematron(false);
myMockSupport = mock(IValidationSupport.class);
ValidationSupportChain validationSupport = new ValidationSupportChain(myMockSupport, myDefaultValidationSupport);
myInstanceVal = new FhirInstanceValidator(validationSupport);
myVal.registerValidatorModule(myInstanceVal);
mySupportedCodeSystemsForExpansion = new HashMap<String, ValueSet.ValueSetExpansionComponent>();
myValidConcepts = new ArrayList<String>();
when(myMockSupport.expandValueSet(any(FhirContext.class), any(ConceptSetComponent.class))).thenAnswer(new Answer<ValueSetExpansionComponent>() {
@Override
public ValueSetExpansionComponent answer(InvocationOnMock theInvocation) throws Throwable {
ConceptSetComponent arg = (ConceptSetComponent) theInvocation.getArguments()[0];
ValueSetExpansionComponent retVal = mySupportedCodeSystemsForExpansion.get(arg.getSystem());
if (retVal == null) {
retVal = myDefaultValidationSupport.expandValueSet(any(FhirContext.class), arg);
}
ourLog.debug("expandValueSet({}) : {}", new Object[]{theInvocation.getArguments()[0], retVal});
return retVal;
}
});
when(myMockSupport.isCodeSystemSupported(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock theInvocation) throws Throwable {
boolean retVal = myValidSystems.contains(theInvocation.getArguments()[1]);
ourLog.debug("isCodeSystemSupported({}) : {}", new Object[]{theInvocation.getArguments()[1], retVal});
return retVal;
}
});
when(myMockSupport.fetchResource(any(FhirContext.class), any(Class.class), any(String.class))).thenAnswer(new Answer<IBaseResource>() {
@Override
public IBaseResource answer(InvocationOnMock theInvocation) throws Throwable {
IBaseResource retVal;
String id = (String) theInvocation.getArguments()[2];
if ("Questionnaire/q_jon".equals(id)) {
retVal = ourCtx.newJsonParser().parseResource(IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/q_jon.json")));
} else {
retVal = myDefaultValidationSupport.fetchResource((FhirContext) theInvocation.getArguments()[0], (Class<IBaseResource>) theInvocation.getArguments()[1], id);
}
ourLog.debug("fetchResource({}, {}) : {}", new Object[]{theInvocation.getArguments()[1], id, retVal});
return retVal;
}
});
when(myMockSupport.validateCode(any(FhirContext.class), any(String.class), any(String.class), any(String.class))).thenAnswer(new Answer<CodeValidationResult>() {
@Override
public CodeValidationResult answer(InvocationOnMock theInvocation) throws Throwable {
FhirContext ctx = (FhirContext) theInvocation.getArguments()[0];
String system = (String) theInvocation.getArguments()[1];
String code = (String) theInvocation.getArguments()[2];
CodeValidationResult retVal;
if (myValidConcepts.contains(system + "___" + code)) {
retVal = new CodeValidationResult(new ConceptDefinitionComponent(new CodeType(code)));
} else {
retVal = myDefaultValidationSupport.validateCode(ctx, system, code, (String) theInvocation.getArguments()[2]);
}
ourLog.debug("validateCode({}, {}, {}) : {}", new Object[]{system, code, (String) theInvocation.getArguments()[2], retVal});
return retVal;
}
});
when(myMockSupport.fetchCodeSystem(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<CodeSystem>() {
@Override
public CodeSystem answer(InvocationOnMock theInvocation) throws Throwable {
CodeSystem retVal = myDefaultValidationSupport.fetchCodeSystem((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
ourLog.debug("fetchCodeSystem({}) : {}", new Object[]{(String) theInvocation.getArguments()[1], retVal});
return retVal;
}
});
when(myMockSupport.fetchStructureDefinition(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<StructureDefinition>() {
@Override
public StructureDefinition answer(InvocationOnMock theInvocation) throws Throwable {
StructureDefinition retVal = myDefaultValidationSupport.fetchStructureDefinition((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
ourLog.debug("fetchStructureDefinition({}) : {}", new Object[]{(String) theInvocation.getArguments()[1], retVal});
return retVal;
}
});
when(myMockSupport.fetchAllStructureDefinitions(any(FhirContext.class))).thenAnswer(new Answer<List<StructureDefinition>>() {
@Override
public List<StructureDefinition> answer(InvocationOnMock theInvocation) throws Throwable {
List<StructureDefinition> retVal = myDefaultValidationSupport.fetchAllStructureDefinitions((FhirContext) theInvocation.getArguments()[0]);
ourLog.debug("fetchAllStructureDefinitions()", new Object[]{});
return retVal;
}
});
}
private Object defaultString(Integer theLocationLine) {
return theLocationLine != null ? theLocationLine.toString() : "";
}
private List<SingleValidationMessage> logResultsAndReturnAll(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {}:{} {} - {}",
new Object[]{index, next.getSeverity(), defaultString(next.getLocationLine()), defaultString(next.getLocationCol()), next.getLocationString(), next.getMessage()});
index++;
retVal.add(next);
}
return retVal;
}
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {} - {}", new Object[]{index, next.getSeverity(), next.getLocationString(), next.getMessage()});
index++;
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
retVal.add(next);
}
}
return retVal;
}
/**
* See #531
*/
@ -119,46 +219,33 @@ public class FhirInstanceValidatorDstu3Test {
}
/**
* See #370
*/
@Test
public void testValidateRelatedPerson() {
public void testIsNoTerminologyChecks() {
assertFalse(myInstanceVal.isNoTerminologyChecks());
myInstanceVal.setNoTerminologyChecks(true);
assertTrue(myInstanceVal.isNoTerminologyChecks());
}
/*
* Try with a code that is in http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
* and therefore should validate
*/
RelatedPerson rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("c");
@Test
public void testValidateBigRawJsonResource() throws Exception {
InputStream stream = FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/conformance.json.gz");
stream = new GZIPInputStream(stream);
String input = IOUtils.toString(stream);
ValidationResult results = myVal.validateWithResult(rp);
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, empty());
long start = System.currentTimeMillis();
ValidationResult output = null;
int passes = 1;
for (int i = 0; i < passes; i++) {
ourLog.info("Pass {}", i + 1);
output = myVal.validateWithResult(input);
}
/*
* Code system is case insensitive, so try with capital C
*/
rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("C");
long delay = System.currentTimeMillis() - start;
long per = delay / passes;
results = myVal.validateWithResult(rp);
outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, empty());
/*
* Now a bad code
*/
rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("GAGAGAGA");
results = myVal.validateWithResult(rp);
outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, not(empty()));
logResultsAndReturnAll(output);
ourLog.info("Took {} ms -- {}ms / pass", delay, per);
}
@Test
@ -196,21 +283,6 @@ public class FhirInstanceValidatorDstu3Test {
ourLog.info("Validated the following:\n{}", ids);
}
/**
* FHIRPathEngine was throwing Error...
*/
@Test
public void testValidateCrucibleCarePlan() throws Exception {
org.hl7.fhir.dstu3.model.Bundle bundle;
String name = "profiles-resources";
ourLog.info("Uploading " + name);
String vsContents;
vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/crucible-condition.xml"), "UTF-8");
ValidationResult output = myVal.validateWithResult(vsContents);
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
}
@Test
@Ignore
public void testValidateBundleWithObservations() throws Exception {
@ -240,6 +312,21 @@ public class FhirInstanceValidatorDstu3Test {
}
/**
* FHIRPathEngine was throwing Error...
*/
@Test
public void testValidateCrucibleCarePlan() throws Exception {
org.hl7.fhir.dstu3.model.Bundle bundle;
String name = "profiles-resources";
ourLog.info("Uploading " + name);
String vsContents;
vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/crucible-condition.xml"), "UTF-8");
ValidationResult output = myVal.validateWithResult(vsContents);
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
}
@Test
public void testValidateDocument() throws Exception {
String vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/sample-document.xml"), "UTF-8");
@ -249,184 +336,6 @@ public class FhirInstanceValidatorDstu3Test {
assertTrue(output.isSuccessful());
}
/**
* A reference with only an identifier should be valid
*/
@Test
public void testValidateReferenceWithIdentifierValid() throws Exception {
Patient p = new Patient();
p.getManagingOrganization().getIdentifier().setSystem("http://acme.org");
p.getManagingOrganization().getIdentifier().setValue("foo");
ValidationResult output = myVal.validateWithResult(p);
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
assertThat(nonInfo, empty());
}
/**
* A reference with only an identifier should be valid
*/
@Test
public void testValidateReferenceWithDisplayValid() throws Exception {
Patient p = new Patient();
p.getManagingOrganization().setDisplay("HELLO");
ValidationResult output = myVal.validateWithResult(p);
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
assertThat(nonInfo, empty());
}
@SuppressWarnings("unchecked")
@Before
public void before() {
myVal = ourCtx.newValidator();
myVal.setValidateAgainstStandardSchema(false);
myVal.setValidateAgainstStandardSchematron(false);
myMockSupport = mock(IValidationSupport.class);
ValidationSupportChain validationSupport = new ValidationSupportChain(myMockSupport, myDefaultValidationSupport);
myInstanceVal = new FhirInstanceValidator(validationSupport);
myVal.registerValidatorModule(myInstanceVal);
mySupportedCodeSystemsForExpansion = new HashMap<String, ValueSet.ValueSetExpansionComponent>();
myValidConcepts = new ArrayList<String>();
when(myMockSupport.expandValueSet(any(FhirContext.class), any(ConceptSetComponent.class))).thenAnswer(new Answer<ValueSetExpansionComponent>() {
@Override
public ValueSetExpansionComponent answer(InvocationOnMock theInvocation) throws Throwable {
ConceptSetComponent arg = (ConceptSetComponent) theInvocation.getArguments()[0];
ValueSetExpansionComponent retVal = mySupportedCodeSystemsForExpansion.get(arg.getSystem());
if (retVal == null) {
retVal = myDefaultValidationSupport.expandValueSet(any(FhirContext.class), arg);
}
ourLog.debug("expandValueSet({}) : {}", new Object[] { theInvocation.getArguments()[0], retVal });
return retVal;
}
});
when(myMockSupport.isCodeSystemSupported(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock theInvocation) throws Throwable {
boolean retVal = myValidSystems.contains(theInvocation.getArguments()[1]);
ourLog.debug("isCodeSystemSupported({}) : {}", new Object[] { theInvocation.getArguments()[1], retVal });
return retVal;
}
});
when(myMockSupport.fetchResource(any(FhirContext.class), any(Class.class), any(String.class))).thenAnswer(new Answer<IBaseResource>() {
@Override
public IBaseResource answer(InvocationOnMock theInvocation) throws Throwable {
IBaseResource retVal;
String id = (String) theInvocation.getArguments()[2];
if ("Questionnaire/q_jon".equals(id)) {
retVal = ourCtx.newJsonParser().parseResource(IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/q_jon.json")));
} else {
retVal = myDefaultValidationSupport.fetchResource((FhirContext) theInvocation.getArguments()[0], (Class<IBaseResource>) theInvocation.getArguments()[1], id);
}
ourLog.debug("fetchResource({}, {}) : {}", new Object[] { theInvocation.getArguments()[1], id, retVal });
return retVal;
}
});
when(myMockSupport.validateCode(any(FhirContext.class), any(String.class), any(String.class), any(String.class))).thenAnswer(new Answer<CodeValidationResult>() {
@Override
public CodeValidationResult answer(InvocationOnMock theInvocation) throws Throwable {
FhirContext ctx = (FhirContext) theInvocation.getArguments()[0];
String system = (String) theInvocation.getArguments()[1];
String code = (String) theInvocation.getArguments()[2];
CodeValidationResult retVal;
if (myValidConcepts.contains(system + "___" + code)) {
retVal = new CodeValidationResult(new ConceptDefinitionComponent(new CodeType(code)));
} else {
retVal = myDefaultValidationSupport.validateCode(ctx, system, code, (String) theInvocation.getArguments()[2]);
}
ourLog.debug("validateCode({}, {}, {}) : {}", new Object[] { system, code, (String) theInvocation.getArguments()[2], retVal });
return retVal;
}
});
when(myMockSupport.fetchCodeSystem(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<CodeSystem>() {
@Override
public CodeSystem answer(InvocationOnMock theInvocation) throws Throwable {
CodeSystem retVal = myDefaultValidationSupport.fetchCodeSystem((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
ourLog.debug("fetchCodeSystem({}) : {}", new Object[] { (String) theInvocation.getArguments()[1], retVal });
return retVal;
}
});
when(myMockSupport.fetchStructureDefinition(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<StructureDefinition>() {
@Override
public StructureDefinition answer(InvocationOnMock theInvocation) throws Throwable {
StructureDefinition retVal = myDefaultValidationSupport.fetchStructureDefinition((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
ourLog.debug("fetchStructureDefinition({}) : {}", new Object[] { (String) theInvocation.getArguments()[1], retVal });
return retVal;
}
});
when(myMockSupport.fetchAllStructureDefinitions(any(FhirContext.class))).thenAnswer(new Answer<List<StructureDefinition>>() {
@Override
public List<StructureDefinition> answer(InvocationOnMock theInvocation) throws Throwable {
List<StructureDefinition> retVal = myDefaultValidationSupport.fetchAllStructureDefinitions((FhirContext) theInvocation.getArguments()[0]);
ourLog.debug("fetchAllStructureDefinitions()", new Object[] {});
return retVal;
}
});
}
private Object defaultString(Integer theLocationLine) {
return theLocationLine != null ? theLocationLine.toString() : "";
}
private List<SingleValidationMessage> logResultsAndReturnAll(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {}:{} {} - {}",
new Object[] { index, next.getSeverity(), defaultString(next.getLocationLine()), defaultString(next.getLocationCol()), next.getLocationString(), next.getMessage() });
index++;
retVal.add(next);
}
return retVal;
}
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {} - {}", new Object[] { index, next.getSeverity(), next.getLocationString(), next.getMessage() });
index++;
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
retVal.add(next);
}
}
return retVal;
}
@Test
public void testValidateBigRawJsonResource() throws Exception {
InputStream stream = FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/conformance.json.gz");
stream = new GZIPInputStream(stream);
String input = IOUtils.toString(stream);
long start = System.currentTimeMillis();
ValidationResult output = null;
int passes = 1;
for (int i = 0; i < passes; i++) {
ourLog.info("Pass {}", i + 1);
output = myVal.validateWithResult(input);
}
long delay = System.currentTimeMillis() - start;
long per = delay / passes;
logResultsAndReturnAll(output);
ourLog.info("Took {} ms -- {}ms / pass", delay, per);
}
@Test
public void testValidateQuestionnaireResponse() throws IOException {
String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/qr_jon.xml"));
@ -447,6 +356,40 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(output.toString(), 0, output.getMessages().size());
}
@Test
public void testValidateRawJsonResourceBadAttributes() {
//@formatter:off
String input =
"{" +
"\"resourceType\":\"Patient\"," +
"\"id\":\"123\"," +
"\"foo\":\"123\"" +
"}";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
ourLog.info(output.getMessages().get(0).getLocationString());
ourLog.info(output.getMessages().get(0).getMessage());
assertEquals("/Patient", output.getMessages().get(0).getLocationString());
assertEquals("Unrecognised property '@foo'", output.getMessages().get(0).getMessage());
}
@Test
public void testValidateRawJsonResourceFromExamples() throws Exception {
// @formatter:off
String input = IOUtils.toString(FhirInstanceValidator.class.getResourceAsStream("/testscript-search.json"));
// @formatter:on
ValidationResult output = myVal.validateWithResult(input);
logResultsAndReturnNonInformationalOnes(output);
// assertEquals(output.toString(), 1, output.getMessages().size());
// ourLog.info(output.getMessages().get(0).getLocationString());
// ourLog.info(output.getMessages().get(0).getMessage());
// assertEquals("/foo", output.getMessages().get(0).getLocationString());
// assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
}
@Test
public void testValidateRawJsonResourceWithUnknownExtension() {
@ -514,65 +457,6 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(ResultSeverityEnum.ERROR, output.getMessages().get(0).getSeverity());
}
@Test
public void testValidateRawXmlWithMissingRootNamespace() {
//@formatter:off
String input = ""
+ "<Patient>"
+ " <text>"
+ " <status value=\"generated\"/>"
+ " <div xmlns=\"http://www.w3.org/1999/xhtml\">Some narrative</div>"
+ " </text>"
+ " <name>"
+ " <use value=\"official\"/>"
+ " <family value=\"Doe\"/>"
+ " <given value=\"John\"/>"
+ " </name>"
+ " <gender value=\"male\"/>"
+ " <birthDate value=\"1974-12-25\"/>"
+ "</Patient>";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
assertEquals("This cannot be parsed as a FHIR object (no namespace)", output.getMessages().get(0).getMessage());
ourLog.info(output.getMessages().get(0).getLocationString());
}
@Test
public void testValidateRawJsonResourceBadAttributes() {
//@formatter:off
String input =
"{" +
"\"resourceType\":\"Patient\"," +
"\"id\":\"123\"," +
"\"foo\":\"123\"" +
"}";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
ourLog.info(output.getMessages().get(0).getLocationString());
ourLog.info(output.getMessages().get(0).getMessage());
assertEquals("/Patient", output.getMessages().get(0).getLocationString());
assertEquals("Unrecognised property '@foo'", output.getMessages().get(0).getMessage());
}
@Test
public void testValidateRawJsonResourceFromExamples() throws Exception {
// @formatter:off
String input = IOUtils.toString(FhirInstanceValidator.class.getResourceAsStream("/testscript-search.json"));
// @formatter:on
ValidationResult output = myVal.validateWithResult(input);
logResultsAndReturnNonInformationalOnes(output);
// assertEquals(output.toString(), 1, output.getMessages().size());
// ourLog.info(output.getMessages().get(0).getLocationString());
// ourLog.info(output.getMessages().get(0).getMessage());
// assertEquals("/foo", output.getMessages().get(0).getLocationString());
// assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
}
@Test
public void testValidateRawXmlResource() {
// @formatter:off
@ -583,6 +467,21 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(output.toString(), 0, output.getMessages().size());
}
@Test
public void testValidateRawXmlResourceBadAttributes() {
//@formatter:off
String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "<foo value=\"222\"/>"
+ "</Patient>";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
ourLog.info(output.getMessages().get(0).getLocationString());
ourLog.info(output.getMessages().get(0).getMessage());
assertEquals("/f:Patient", output.getMessages().get(0).getLocationString());
assertEquals("Undefined element 'foo\"", output.getMessages().get(0).getMessage());
}
@Test
public void testValidateRawXmlResourceWithEmptyPrimitive() {
// @formatter:off
@ -598,26 +497,26 @@ public class FhirInstanceValidatorDstu3Test {
@Test
public void testValidateRawXmlResourceWithPrimitiveContainingOnlyAnExtension() {
// @formatter:off
String input = "<ActivityDefinition xmlns=\"http://hl7.org/fhir\">\n" +
" <id value=\"referralToMentalHealthCare\"/>\n" +
" <status value=\"draft\"/>\n" +
" <description value=\"refer to primary care mental-health integrated care program for evaluation and treatment of mental health conditions now\"/>\n" +
" <code>\n" +
" <coding>\n" +
" <!-- Error: Connection to http://localhost:960 refused -->\n" +
" <!--<system value=\"http://snomed.info/sct\"/>-->\n" +
" <code value=\"306206005\"/>\n" +
" </coding>\n" +
" </code>\n" +
" <!-- Specifying this this way results in a null reference exception in the validator -->\n" +
" <timingTiming>\n" +
" <event>\n" +
" <extension url=\"http://fhir.org/cql-expression\">\n" +
" <valueString value=\"Now()\"/>\n" +
" </extension>\n" +
" </event>\n" +
" </timingTiming>\n" +
" </ActivityDefinition>";
String input = "<ActivityDefinition xmlns=\"http://hl7.org/fhir\">\n" +
" <id value=\"referralToMentalHealthCare\"/>\n" +
" <status value=\"draft\"/>\n" +
" <description value=\"refer to primary care mental-health integrated care program for evaluation and treatment of mental health conditions now\"/>\n" +
" <code>\n" +
" <coding>\n" +
" <!-- Error: Connection to http://localhost:960 refused -->\n" +
" <!--<system value=\"http://snomed.info/sct\"/>-->\n" +
" <code value=\"306206005\"/>\n" +
" </coding>\n" +
" </code>\n" +
" <!-- Specifying this this way results in a null reference exception in the validator -->\n" +
" <timingTiming>\n" +
" <event>\n" +
" <extension url=\"http://fhir.org/cql-expression\">\n" +
" <valueString value=\"Now()\"/>\n" +
" </extension>\n" +
" </event>\n" +
" </timingTiming>\n" +
" </ActivityDefinition>";
// @formatter:on
ValidationResult output = myVal.validateWithResult(input);
@ -626,18 +525,97 @@ public class FhirInstanceValidatorDstu3Test {
}
@Test
public void testValidateRawXmlResourceBadAttributes() {
public void testValidateRawXmlWithMissingRootNamespace() {
//@formatter:off
String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "<foo value=\"222\"/>"
+ "</Patient>";
//@formatter:on
String input = ""
+ "<Patient>"
+ " <text>"
+ " <status value=\"generated\"/>"
+ " <div xmlns=\"http://www.w3.org/1999/xhtml\">Some narrative</div>"
+ " </text>"
+ " <name>"
+ " <use value=\"official\"/>"
+ " <family value=\"Doe\"/>"
+ " <given value=\"John\"/>"
+ " </name>"
+ " <gender value=\"male\"/>"
+ " <birthDate value=\"1974-12-25\"/>"
+ "</Patient>";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
assertEquals("This cannot be parsed as a FHIR object (no namespace)", output.getMessages().get(0).getMessage());
ourLog.info(output.getMessages().get(0).getLocationString());
ourLog.info(output.getMessages().get(0).getMessage());
assertEquals("/f:Patient", output.getMessages().get(0).getLocationString());
assertEquals("Undefined element 'foo\"", output.getMessages().get(0).getMessage());
}
/**
* A reference with only an identifier should be valid
*/
@Test
public void testValidateReferenceWithDisplayValid() throws Exception {
Patient p = new Patient();
p.getManagingOrganization().setDisplay("HELLO");
ValidationResult output = myVal.validateWithResult(p);
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
assertThat(nonInfo, empty());
}
/**
* A reference with only an identifier should be valid
*/
@Test
public void testValidateReferenceWithIdentifierValid() throws Exception {
Patient p = new Patient();
p.getManagingOrganization().getIdentifier().setSystem("http://acme.org");
p.getManagingOrganization().getIdentifier().setValue("foo");
ValidationResult output = myVal.validateWithResult(p);
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
assertThat(nonInfo, empty());
}
/**
* See #370
*/
@Test
public void testValidateRelatedPerson() {
/*
* Try with a code that is in http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
* and therefore should validate
*/
RelatedPerson rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("c");
ValidationResult results = myVal.validateWithResult(rp);
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, empty());
/*
* Code system is case insensitive, so try with capital C
*/
rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("C");
results = myVal.validateWithResult(rp);
outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, empty());
/*
* Now a bad code
*/
rp = new RelatedPerson();
rp.getPatient().setReference("Patient/1");
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("GAGAGAGA");
results = myVal.validateWithResult(rp);
outcome = logResultsAndReturnNonInformationalOnes(results);
assertThat(outcome, not(empty()));
}
@Test
@ -729,19 +707,19 @@ public class FhirInstanceValidatorDstu3Test {
@Test
public void testValidateResourceWithDefaultValuesetBadCode() {
//@formatter:off
String input =
String input =
"<Observation xmlns=\"http://hl7.org/fhir\">\n" +
" <status value=\"notvalidcode\"/>\n" +
" <code>\n" +
" <text value=\"No code here!\"/>\n" +
" </code>\n" +
"</Observation>";
" <status value=\"notvalidcode\"/>\n" +
" <code>\n" +
" <text value=\"No code here!\"/>\n" +
" </code>\n" +
"</Observation>";
//@formatter:on
ValidationResult output = myVal.validateWithResult(input);
logResultsAndReturnAll(output);
assertEquals(
"The value provided ('notvalidcode') is not in the value set http://hl7.org/fhir/ValueSet/observation-status (http://hl7.org/fhir/ValueSet/observation-status, and a code is required from this value set) (error message = Unknown code[notvalidcode] in system[null])",
output.getMessages().get(0).getMessage());
"The value provided ('notvalidcode') is not in the value set http://hl7.org/fhir/ValueSet/observation-status (http://hl7.org/fhir/ValueSet/observation-status, and a code is required from this value set) (error message = Unknown code[notvalidcode] in system[null])",
output.getMessages().get(0).getMessage());
}
@Test
@ -759,6 +737,23 @@ public class FhirInstanceValidatorDstu3Test {
}
@Test
public void testValidateResourceWithExampleBindingCodeValidationFailingNonLoinc() {
Observation input = new Observation();
myInstanceVal.setValidationSupport(myMockSupport);
addValidConcept("http://acme.org", "12345");
input.setStatus(ObservationStatus.FINAL);
input.getCode().addCoding().setSystem("http://acme.org").setCode("9988877");
ValidationResult output = myVal.validateWithResult(input);
List<SingleValidationMessage> errors = logResultsAndReturnAll(output);
assertThat(errors.toString(), errors.size(), greaterThan(0));
assertEquals("Unknown code: http://acme.org / 9988877", errors.get(0).getMessage());
}
@Test
public void testValidateResourceWithExampleBindingCodeValidationPassingLoinc() {
Observation input = new Observation();
@ -809,23 +804,6 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(errors.toString(), 0, errors.size());
}
@Test
public void testValidateResourceWithExampleBindingCodeValidationFailingNonLoinc() {
Observation input = new Observation();
myInstanceVal.setValidationSupport(myMockSupport);
addValidConcept("http://acme.org", "12345");
input.setStatus(ObservationStatus.FINAL);
input.getCode().addCoding().setSystem("http://acme.org").setCode("9988877");
ValidationResult output = myVal.validateWithResult(input);
List<SingleValidationMessage> errors = logResultsAndReturnAll(output);
assertThat(errors.toString(), errors.size(), greaterThan(0));
assertEquals("Unknown code: http://acme.org / 9988877", errors.get(0).getMessage());
}
@Test
public void testValidateResourceWithValuesetExpansionBad() {
@ -837,8 +815,8 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(1, all.size());
assertEquals("Patient.identifier.type", all.get(0).getLocationString());
assertEquals(
"None of the codes provided are in the value set http://hl7.org/fhir/ValueSet/identifier-type (http://hl7.org/fhir/ValueSet/identifier-type, and a code should come from this value set unless it has no suitable code) (codes = http://example.com/foo/bar#bar)",
all.get(0).getMessage());
"None of the codes provided are in the value set http://hl7.org/fhir/ValueSet/identifier-type (http://hl7.org/fhir/ValueSet/identifier-type, and a code should come from this value set unless it has no suitable code) (codes = http://example.com/foo/bar#bar)",
all.get(0).getMessage());
assertEquals(ResultSeverityEnum.WARNING, all.get(0).getSeverity());
}
@ -853,13 +831,6 @@ public class FhirInstanceValidatorDstu3Test {
assertEquals(0, all.size());
}
@Test
public void testIsNoTerminologyChecks() {
assertFalse(myInstanceVal.isNoTerminologyChecks());
myInstanceVal.setNoTerminologyChecks(true);
assertTrue(myInstanceVal.isNoTerminologyChecks());
}
@Test
@Ignore
public void testValidateStructureDefinition() throws IOException {
@ -873,6 +844,17 @@ public class FhirInstanceValidatorDstu3Test {
ourLog.info(output.getMessages().get(0).getMessage());
}
@Test
public void testValueWithWhitespace() throws IOException {
String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/dstu3-rick-test.json"), Charsets.UTF_8);
ValidationResult results = myVal.validateWithResult(input);
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
assertEquals(1, outcome.size());
assertThat(outcome.toString(), containsString("value should not start or finish with whitespace"));
}
@AfterClass
public static void afterClassClearContext() {
myDefaultValidationSupport.flush();

View File

@ -1,4 +1,4 @@
package ca.uhn.fhir.validation;
package org.hl7.fhir.dstu3.hapi.validation;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
@ -12,14 +12,14 @@ import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.SingleValidationMessage;
import ca.uhn.fhir.validation.ValidationResult;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;

View File

@ -1,19 +1,14 @@
package org.hl7.fhir.dstu3.hapi.validation;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.*;
import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
import org.apache.commons.io.IOUtils;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.dstu3.model.*;
@ -25,23 +20,35 @@ import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.parser.XmlParserDstu3Test;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.*;
import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class ResourceValidatorDstu3Test {
private static FhirContext ourCtx = FhirContext.forDstu3();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorDstu3Test.class);
private static FhirContext ourCtx = FhirContext.forDstu3();
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {} - {}",
new Object[]{index, next.getSeverity(), next.getLocationString(), next.getMessage()});
index++;
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
retVal.add(next);
}
}
return retVal;
}
/**
@ -75,24 +82,24 @@ public class ResourceValidatorDstu3Test {
assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"2000-15-31\": Invalid date/time format: \"2000-15-31\"", e.getMessage());
}
}
@Test
@Ignore
public void testValidateCareTeamProfile() {
CareTeam careTeam = new CareTeam();
careTeam
.addParticipant()
.setMember(new Reference("Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881"))
.setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828"));
.setMember(new Reference("Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881"))
.setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828"));
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
String encoded = parser.encodeResourceToString(careTeam);
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(encoded);
String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
ourLog.info(resultString);
@ -101,45 +108,29 @@ public class ResourceValidatorDstu3Test {
assertThat(resultString, StringContains.containsString("cvc-pattern-valid"));
}
@Test
public void testValidateCareTeamXsd() {
CareTeam careTeam = new CareTeam();
careTeam
.addParticipant()
.setMember(new Reference("http://example.com/Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881"))
.setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828"));
.setMember(new Reference("http://example.com/Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881"))
.setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828"));
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
String encoded = parser.encodeResourceToString(careTeam);
ourLog.info(encoded);
FhirValidator val = ourCtx.newValidator();
ValidationResult result = val.validateWithResult(encoded);
String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
ourLog.info(resultString);
assertThat(resultString, containsString("No issues detected during validation"));
}
@Test
public void testValidateCodeableConceptContainingOnlyGoodCode() {
Patient p = new Patient();
p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("M");
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult output = val.validateWithResult(p);
List<SingleValidationMessage> all = logResultsAndReturnNonInformationalOnes(output);
assertEquals(0, all.size());
assertEquals(0, output.getMessages().size());
}
@Test
@ -159,24 +150,136 @@ public class ResourceValidatorDstu3Test {
assertEquals(ResultSeverityEnum.WARNING, output.getMessages().get(0).getSeverity());
}
@Test
public void testValidateCodeableConceptContainingOnlyGoodCode() {
Patient p = new Patient();
p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("M");
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
int index = 0;
for (SingleValidationMessage next : theOutput.getMessages()) {
ourLog.info("Result {}: {} - {} - {}",
new Object[] { index, next.getSeverity(), next.getLocationString(), next.getMessage() });
index++;
ValidationResult output = val.validateWithResult(p);
List<SingleValidationMessage> all = logResultsAndReturnNonInformationalOnes(output);
assertEquals(0, all.size());
assertEquals(0, output.getMessages().size());
}
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
retVal.add(next);
}
}
@Test
@Ignore
public void testValidateDifferentPropertyButSameStartsWithPath() throws Exception {
return retVal;
}
EligibilityResponse fhirObj = new EligibilityResponse();
BenefitComponent benComp = fhirObj.addInsurance().addBenefitBalance().addFinancial();
// Test between .benefit[x] and benefitUsed[x]
// benComp.setBenefitUsed(new UnsignedIntType(2));
String input = ourCtx.newXmlParser().encodeResourceToString(fhirObj);
FhirValidator validator = ourCtx.newValidator();
validator.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = validator.validateWithResult(input);
// we should get some results, not an exception
assertEquals(4, result.getMessages().size());
}
@Test
public void testValidateJsonNumericId() {
String input = "{\"resourceType\": \"Patient\",\n" +
" \"id\": 123,\n" +
" \"meta\": {\n" +
" \"versionId\": \"29\",\n" +
" \"lastUpdated\": \"2015-12-22T19:53:11.000Z\"\n" +
" },\n" +
" \"communication\": {\n" +
" \"language\": {\n" +
" \"coding\": [\n" +
" {\n" +
" \"system\": \"urn:ietf:bcp:47\",\n" +
" \"code\": \"hi\",\n" +
" \"display\": \"Hindi\",\n" +
" \"userSelected\": false\n" +
" }],\n" +
" \"text\": \"Hindi\"\n" +
" },\n" +
" \"preferred\": true\n" +
" }\n" +
"}";
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult output = val.validateWithResult(input);
OperationOutcome operationOutcome = (OperationOutcome) output.toOperationOutcome();
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
assertThat(encoded, containsString("Error parsing JSON: the primitive value must be a string"));
}
/**
* Per email from Jon Zammit
*/
@Test
@Ignore
public void testValidateQuestionnaire() throws IOException {
String input = IOUtils.toString(getClass().getResourceAsStream("/questionnaire_jon_z_20160506.xml"), StandardCharsets.UTF_8);
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(input);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String ooencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(ooencoded);
assertTrue(result.isSuccessful());
}
/**
* TODO: re-enable this
*/
@Test
@Ignore
public void testValidateQuestionnaireWithCanonicalUrl() {
String input = "{\n" +
" \"resourceType\": \"Questionnaire\",\n" +
" \"url\": \"http://some.example.url\",\n" +
" \"status\": \"published\",\n" +
" \"subjectType\": [\n" +
" \"Patient\"\n" +
" ],\n" +
" \"item\": [\n" +
" {\n" +
" \"linkId\": \"example-question\",\n" +
" \"text\": \"Is the sky blue?\",\n" +
" \"type\": \"choice\",\n" +
" \"options\": {\n" +
" \"reference\": \"http://loinc.org/vs/LL3044-6\"\n" +
" }\n" +
" }\n" +
" ]\n" +
"}";
Questionnaire q = new Questionnaire();
q = ourCtx.newJsonParser().parseResource(Questionnaire.class, input);
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(q);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
}
/**
* Make sure that the elements that appear in all resources (meta, language, extension, etc) all appear in the correct order
@ -184,7 +287,7 @@ public class ResourceValidatorDstu3Test {
@Test
public void testValidateResourceWithResourceElements() {
XmlParserDstu3Test.TestPatientFor327 patient = new XmlParserDstu3Test.TestPatientFor327();
TestPatientFor327 patient = new TestPatientFor327();
patient.setBirthDate(new Date());
patient.setId("123");
patient.getText().setDivAsString("<div>FOO</div>");
@ -223,6 +326,55 @@ public class ResourceValidatorDstu3Test {
assertThat(ooencoded, containsString("Unknown extension http://foo"));
}
/**
* See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer
*/
@Test
public void testValidateWithExtensionsJson() {
PatientProfileDstu3 myPatient = new PatientProfileDstu3();
myPatient.setId("1");
myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey")));
myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setSystem("furry-white")));
myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393"));
myPatient.addName().setFamily("FamilyName");
myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension"));
IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
String messageString = p.encodeResourceToString(myPatient);
ourLog.info(messageString);
//@formatter:off
assertThat(messageString, stringContainsInOrder(
"meta",
"String Extension",
"Organization/2.25.79433498044103547197447759549862032393",
"furry-grey",
"furry-white",
"FamilyName"
));
assertThat(messageString, not(stringContainsInOrder(
"extension",
"meta"
)));
//@formatter:on
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(messageString);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
assertTrue(result.isSuccessful());
assertThat(messageString, containsString("valueReference"));
assertThat(messageString, not(containsString("valueResource")));
}
/**
* See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer
*/
@ -274,168 +426,27 @@ public class ResourceValidatorDstu3Test {
assertThat(messageString, not(containsString("valueResource")));
}
/**
* Per email from Jon Zammit
*/
@Test
@Ignore
public void testValidateQuestionnaire() throws IOException {
String input = IOUtils.toString(getClass().getResourceAsStream("/questionnaire_jon_z_20160506.xml"), StandardCharsets.UTF_8);
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(input);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String ooencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(ooencoded);
assertTrue(result.isSuccessful());
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
@Test
public void testValidateJsonNumericId() {
String input = "{\"resourceType\": \"Patient\",\n" +
" \"id\": 123,\n" +
" \"meta\": {\n" +
" \"versionId\": \"29\",\n" +
" \"lastUpdated\": \"2015-12-22T19:53:11.000Z\"\n" +
" },\n" +
" \"communication\": {\n" +
" \"language\": {\n" +
" \"coding\": [\n" +
" {\n" +
" \"system\": \"urn:ietf:bcp:47\",\n" +
" \"code\": \"hi\",\n" +
" \"display\": \"Hindi\",\n" +
" \"userSelected\": false\n" +
" }],\n" +
" \"text\": \"Hindi\"\n" +
" },\n" +
" \"preferred\": true\n" +
" }\n" +
"}";
@ResourceDef(name = "Patient")
public static class TestPatientFor327 extends Patient {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult output = val.validateWithResult(input);
private static final long serialVersionUID = 1L;
OperationOutcome operationOutcome = (OperationOutcome) output.toOperationOutcome();
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
@Child(name = "testCondition")
@ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false)
private List<Reference> testConditions = null;
assertThat(encoded, containsString("Error parsing JSON: the primitive value must be a string"));
public List<Reference> getConditions() {
return this.testConditions;
}
}
/**
* See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer
*/
@Test
public void testValidateWithExtensionsJson() {
PatientProfileDstu3 myPatient = new PatientProfileDstu3();
myPatient.setId("1");
myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey")));
myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setSystem("furry-white")));
myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393"));
myPatient.addName().setFamily("FamilyName");
myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension"));
IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
String messageString = p.encodeResourceToString(myPatient);
ourLog.info(messageString);
//@formatter:off
assertThat(messageString, stringContainsInOrder(
"meta",
"String Extension",
"Organization/2.25.79433498044103547197447759549862032393",
"furry-grey",
"furry-white",
"FamilyName"
));
assertThat(messageString, not(stringContainsInOrder(
"extension",
"meta"
)));
//@formatter:on
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(messageString);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
assertTrue(result.isSuccessful());
assertThat(messageString, containsString("valueReference"));
assertThat(messageString, not(containsString("valueResource")));
}
@Test
@Ignore
public void testValidateDifferentPropertyButSameStartsWithPath() throws Exception {
EligibilityResponse fhirObj = new EligibilityResponse();
BenefitComponent benComp = fhirObj.addInsurance().addBenefitBalance().addFinancial();
// Test between .benefit[x] and benefitUsed[x]
// benComp.setBenefitUsed(new UnsignedIntType(2));
String input = ourCtx.newXmlParser().encodeResourceToString(fhirObj);
FhirValidator validator = ourCtx.newValidator();
validator.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = validator.validateWithResult(input);
// we should get some results, not an exception
assertEquals(4, result.getMessages().size());
}
/**
* TODO: re-enable this
*/
@Test
@Ignore
public void testValidateQuestionnaireWithCanonicalUrl() {
String input = "{\n" +
" \"resourceType\": \"Questionnaire\",\n" +
" \"url\": \"http://some.example.url\",\n" +
" \"status\": \"published\",\n" +
" \"subjectType\": [\n" +
" \"Patient\"\n" +
" ],\n" +
" \"item\": [\n" +
" {\n" +
" \"linkId\": \"example-question\",\n" +
" \"text\": \"Is the sky blue?\",\n" +
" \"type\": \"choice\",\n" +
" \"options\": {\n" +
" \"reference\": \"http://loinc.org/vs/LL3044-6\"\n" +
" }\n" +
" }\n" +
" ]\n" +
"}";
Questionnaire q = new Questionnaire();
q = ourCtx.newJsonParser().parseResource(Questionnaire.class, input);
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(q);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
ourLog.info(encoded);
public void setCondition(List<Reference> ref) {
this.testConditions = ref;
}
}
}

View File

@ -1,9 +1,11 @@
package ca.uhn.fhir.validation;
package org.hl7.fhir.dstu3.hapi.validation;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import org.junit.AfterClass;
import org.junit.Test;

View File

@ -1,322 +1,323 @@
package org.hl7.fhir.dstu3.hapi.validation;
import static org.junit.Assert.assertEquals;
import java.util.*;
import javax.annotation.Nullable;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.utils.StructureMapUtilities;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
public class StructureMapTest {
/**
* The logger object.
*/
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StructureMapTest.class);
/**
* The basic fhir context used to parse structure definitions.
*/
FhirContext context;
/**
* HapiFhirContext used when building strucutre map utilities.
*/
IWorkerContext hapiContext;
/**
* path to the files used to test the profile generator.
*/
String resourcePath = null;
/**
* Used to validate definitions as well as add new structure definitions to a registry.
*/
PrePopulatedValidationSupport validationSupport;
public StructureMap.StructureMapGroupRuleSourceComponent buildSource(String context, @Nullable String element, @Nullable String variable, @Nullable String type, @Nullable Integer min,
@Nullable String max) {
StructureMap.StructureMapGroupRuleSourceComponent retVal = new StructureMap.StructureMapGroupRuleSourceComponent();
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (type != null)
retVal.setType(type);
if (min != null)
retVal.setMin(min);
if (max != null)
retVal.setMax(max);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleSourceComponent> buildSourceList(StructureMap.StructureMapGroupRuleSourceComponent[] sources) {
List<StructureMap.StructureMapGroupRuleSourceComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleSourceComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public StructureMap.StructureMapGroupRuleTargetComponent buildTarget(@Nullable String context, @Nullable String element, @Nullable String variable,
@Nullable StructureMap.StructureMapTransform transform, @Nullable TargetParam[] params) throws Exception {
StructureMap.StructureMapGroupRuleTargetComponent retVal = new StructureMap.StructureMapGroupRuleTargetComponent();
if (context != null)
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (transform != null)
retVal.setTransform(transform);
if (params != null) {
if (params.length > 0)
retVal.setParameter(this.constructParameters(params));
}
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetComponent> buildTargetList(StructureMap.StructureMapGroupRuleTargetComponent[] sources) {
List<StructureMap.StructureMapGroupRuleTargetComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleTargetComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public List<StructureMap.StructureMapGroupComponent> buildTestGroup() throws Exception {
List<StructureMap.StructureMapGroupComponent> retVal = new ArrayList<StructureMap.StructureMapGroupComponent>();
StructureMap.StructureMapGroupComponent group = new StructureMap.StructureMapGroupComponent();
group.setName("TestStructureToCoding");
group.setTypeMode(StructureMap.StructureMapGroupTypeMode.TYPEANDTYPES);
group.setInput(this.buildTestInput());
group.setRule(this.buildTestRules());
retVal.add(group);
return retVal;
}
public List<StructureMap.StructureMapGroupInputComponent> buildTestInput() {
List<StructureMap.StructureMapGroupInputComponent> retVal = new ArrayList<StructureMap.StructureMapGroupInputComponent>();
StructureMap.StructureMapGroupInputComponent sourceIn = new StructureMap.StructureMapGroupInputComponent();
StructureMap.StructureMapGroupInputComponent targetIn = new StructureMap.StructureMapGroupInputComponent();
sourceIn.setName("source");
sourceIn.setType("TestStructure");
sourceIn.setMode(StructureMap.StructureMapInputMode.SOURCE);
targetIn.setName("target");
targetIn.setType("http://hl7.org/fhir/StructureDefinition/Coding");
targetIn.setMode(StructureMap.StructureMapInputMode.TARGET);
retVal.add(sourceIn);
retVal.add(targetIn);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleComponent> buildTestRules() throws Exception {
List<StructureMap.StructureMapGroupRuleComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleComponent>();
StructureMap.StructureMapGroupRuleComponent codingSystem = new StructureMap.StructureMapGroupRuleComponent();
StructureMap.StructureMapGroupRuleComponent codingExtension = new StructureMap.StructureMapGroupRuleComponent();
codingSystem.setName("Coding.System");
codingSystem.setSource(this.buildSourceList(new StructureMap.StructureMapGroupRuleSourceComponent[] {
this.buildSource("source", "system", "v", null, null, null)
}));
codingSystem.setTarget(this.buildTargetList(new StructureMap.StructureMapGroupRuleTargetComponent[] {
this.buildTarget("target", "system", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("Id", "v") })
}));
codingExtension.setName("Coding.Extension");
codingExtension.setSource(this.buildSourceList(new StructureMap.StructureMapGroupRuleSourceComponent[] {
this.buildSource("source", "system", "v", null, null, null)
}));
codingExtension.setTarget(this.buildTargetList(new StructureMap.StructureMapGroupRuleTargetComponent[] {
this.buildTarget("target", "extension", "ex", null, new TargetParam[] { new TargetParam("", "") }),
this.buildTarget("ex", "url", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("Id", "v") }),
this.buildTarget("ex", "value", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("String", "v") })
}));
retVal.add(codingSystem);
retVal.add(codingExtension);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetParameterComponent> constructParameters(TargetParam[] params) throws Exception {
List<StructureMap.StructureMapGroupRuleTargetParameterComponent> parameterComponents = new ArrayList<StructureMap.StructureMapGroupRuleTargetParameterComponent>();
for (TargetParam tp : params) {
if (tp.getType() == "Id") // TODO: Convert TypeParam.Type into an Enum.
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new IdType().setValue(tp.getValue())));
else if (tp.getType() == "String")
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue((new StringType().setValue(tp.getValue()))));
else if (tp.getType() == "Boolean") {
boolean bValue = Boolean.getBoolean(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new BooleanType().setValue(bValue)));
} else if (tp.getType() == "Integer") {
int iValue = Integer.getInteger(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new IntegerType().setValue(iValue)));
} else if (tp.getType() == "Decimal") {
long lValue = Long.getLong(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new DecimalType(lValue)));
}
}
return parameterComponents;
}
public List<StructureMap.StructureMapStructureComponent> createMapStructureList() {
List<StructureMap.StructureMapStructureComponent> retVal = new ArrayList<StructureMap.StructureMapStructureComponent>();
StructureMap.StructureMapStructureComponent source = new StructureMap.StructureMapStructureComponent();
StructureMap.StructureMapStructureComponent target = new StructureMap.StructureMapStructureComponent();
source.setUrl("http://opencimi.org/structuredefinition/TestStructure");
source.setMode(StructureMap.StructureMapModelMode.SOURCE);
target.setUrl("http://hl7.org/fhir/StructureDefinition/Coding");
target.setMode(StructureMap.StructureMapModelMode.TARGET);
retVal.add(source);
retVal.add(target);
return retVal;
}
public StructureDefinition.StructureDefinitionDifferentialComponent createTestDiff() {
StructureDefinition.StructureDefinitionDifferentialComponent retVal = new StructureDefinition.StructureDefinitionDifferentialComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition.StructureDefinitionSnapshotComponent createTestSnapshot() {
StructureDefinition.StructureDefinitionSnapshotComponent retVal = new StructureDefinition.StructureDefinitionSnapshotComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
ed.setMin(1);
ed.setMax("1");
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition createTestStructure() {
StructureDefinition sd = new StructureDefinition();
sd.setId("TestStructure");
sd.setUrl("http://opencimi.org/structuredefinition/TestStructure");
sd.setStatus(Enumerations.PublicationStatus.DRAFT);
sd.setName("TestStructure");
sd.setType("TestStructure");
sd.setSnapshot(this.createTestSnapshot());
sd.setDifferential(this.createTestDiff());
sd.setKind(StructureDefinition.StructureDefinitionKind.LOGICAL);
return sd;
}
public StructureMap createTestStructuremap() throws Exception {
StructureMap retMap = new StructureMap();
retMap.setUrl("http://opencimi.org/structuremap/testtransform");
retMap.setName("TestTransform");
retMap.setStatus(Enumerations.PublicationStatus.DRAFT);
retMap.setStructure(this.createMapStructureList());
retMap.setGroup(this.buildTestGroup());
return retMap;
}
/**
* Sets up the resource paths as well as create the contexts using a defalut validator to start with.
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
if (this.context == null) {
this.context = FhirContext.forDstu3();
}
}
/**
* See #682
*/
@Test
public void testMappingTransform() throws Exception {
Map<String, StructureMap> maps = new HashMap<String, StructureMap>(); // Instantiate a hashmap for StructureMaps
this.validationSupport = new PrePopulatedValidationSupport(); // Create Validation Instance
for (StructureDefinition sd : new DefaultProfileValidationSupport().fetchAllStructureDefinitions(this.context)) { // Read in the default Structure Definitions into a validator that allows custom
// declared structure definitions.
this.validationSupport.addStructureDefinition(sd);
}
StructureDefinition sd1 = this.createTestStructure(); // Calls a method that constructs a comp
this.validationSupport.addStructureDefinition(sd1); // Add custom structure to validation support.
this.hapiContext = new HapiWorkerContext(this.context, this.validationSupport);// Init the Hapi Work
StructureMap map = this.createTestStructuremap();
maps.put(map.getUrl(), map);
StructureMapUtilities scu = new StructureMapUtilities(hapiContext, maps, null, null);
List<StructureDefinition> result = scu.analyse(null, map).getProfiles();
assertEquals(1, result.size());
ourLog.info(context.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.get(0)));
}
public class TargetParam {
private String type;
private String value;
public TargetParam(String type, String value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public String getValue() {
return value;
}
public void setType(String type) {
this.type = type;
}
public void setValue(String value) {
this.value = value;
}
}
}
package org.hl7.fhir.dstu3.hapi.validation;
import static org.junit.Assert.assertEquals;
import java.util.*;
import javax.annotation.Nullable;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.utils.StructureMapUtilities;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
public class StructureMapTest {
/**
* The logger object.
*/
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StructureMapTest.class);
/**
* The basic fhir context used to parse structure definitions.
*/
FhirContext context;
/**
* HapiFhirContext used when building strucutre map utilities.
*/
IWorkerContext hapiContext;
/**
* path to the files used to test the profile generator.
*/
String resourcePath = null;
/**
* Used to validate definitions as well as add new structure definitions to a registry.
*/
PrePopulatedValidationSupport validationSupport;
public StructureMap.StructureMapGroupRuleSourceComponent buildSource(String context, @Nullable String element, @Nullable String variable, @Nullable String type, @Nullable Integer min,
@Nullable String max) {
StructureMap.StructureMapGroupRuleSourceComponent retVal = new StructureMap.StructureMapGroupRuleSourceComponent();
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (type != null)
retVal.setType(type);
if (min != null)
retVal.setMin(min);
if (max != null)
retVal.setMax(max);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleSourceComponent> buildSourceList(StructureMap.StructureMapGroupRuleSourceComponent[] sources) {
List<StructureMap.StructureMapGroupRuleSourceComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleSourceComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public StructureMap.StructureMapGroupRuleTargetComponent buildTarget(@Nullable String context, @Nullable String element, @Nullable String variable,
@Nullable StructureMap.StructureMapTransform transform, @Nullable TargetParam[] params) throws Exception {
StructureMap.StructureMapGroupRuleTargetComponent retVal = new StructureMap.StructureMapGroupRuleTargetComponent();
if (context != null)
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (transform != null)
retVal.setTransform(transform);
if (params != null) {
if (params.length > 0)
retVal.setParameter(this.constructParameters(params));
}
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetComponent> buildTargetList(StructureMap.StructureMapGroupRuleTargetComponent[] sources) {
List<StructureMap.StructureMapGroupRuleTargetComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleTargetComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public List<StructureMap.StructureMapGroupComponent> buildTestGroup() throws Exception {
List<StructureMap.StructureMapGroupComponent> retVal = new ArrayList<StructureMap.StructureMapGroupComponent>();
StructureMap.StructureMapGroupComponent group = new StructureMap.StructureMapGroupComponent();
group.setName("TestStructureToCoding");
group.setTypeMode(StructureMap.StructureMapGroupTypeMode.TYPEANDTYPES);
group.setInput(this.buildTestInput());
group.setRule(this.buildTestRules());
retVal.add(group);
return retVal;
}
public List<StructureMap.StructureMapGroupInputComponent> buildTestInput() {
List<StructureMap.StructureMapGroupInputComponent> retVal = new ArrayList<StructureMap.StructureMapGroupInputComponent>();
StructureMap.StructureMapGroupInputComponent sourceIn = new StructureMap.StructureMapGroupInputComponent();
StructureMap.StructureMapGroupInputComponent targetIn = new StructureMap.StructureMapGroupInputComponent();
sourceIn.setName("source");
sourceIn.setType("TestStructure");
sourceIn.setMode(StructureMap.StructureMapInputMode.SOURCE);
targetIn.setName("target");
targetIn.setType("http://hl7.org/fhir/StructureDefinition/Coding");
targetIn.setMode(StructureMap.StructureMapInputMode.TARGET);
retVal.add(sourceIn);
retVal.add(targetIn);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleComponent> buildTestRules() throws Exception {
List<StructureMap.StructureMapGroupRuleComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleComponent>();
StructureMap.StructureMapGroupRuleComponent codingSystem = new StructureMap.StructureMapGroupRuleComponent();
StructureMap.StructureMapGroupRuleComponent codingExtension = new StructureMap.StructureMapGroupRuleComponent();
codingSystem.setName("Coding.System");
codingSystem.setSource(this.buildSourceList(new StructureMap.StructureMapGroupRuleSourceComponent[] {
this.buildSource("source", "system", "v", null, null, null)
}));
codingSystem.setTarget(this.buildTargetList(new StructureMap.StructureMapGroupRuleTargetComponent[] {
this.buildTarget("target", "system", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("Id", "v") })
}));
codingExtension.setName("Coding.Extension");
codingExtension.setSource(this.buildSourceList(new StructureMap.StructureMapGroupRuleSourceComponent[] {
this.buildSource("source", "system", "v", null, null, null)
}));
codingExtension.setTarget(this.buildTargetList(new StructureMap.StructureMapGroupRuleTargetComponent[] {
this.buildTarget("target", "extension", "ex", null, new TargetParam[] { new TargetParam("", "") }),
this.buildTarget("ex", "url", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("Id", "v") }),
this.buildTarget("ex", "value", null, StructureMap.StructureMapTransform.COPY, new TargetParam[] { new TargetParam("String", "v") })
}));
retVal.add(codingSystem);
retVal.add(codingExtension);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetParameterComponent> constructParameters(TargetParam[] params) throws Exception {
List<StructureMap.StructureMapGroupRuleTargetParameterComponent> parameterComponents = new ArrayList<StructureMap.StructureMapGroupRuleTargetParameterComponent>();
for (TargetParam tp : params) {
if (tp.getType() == "Id") // TODO: Convert TypeParam.Type into an Enum.
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new IdType().setValue(tp.getValue())));
else if (tp.getType() == "String")
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue((new StringType().setValue(tp.getValue()))));
else if (tp.getType() == "Boolean") {
boolean bValue = Boolean.getBoolean(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new BooleanType().setValue(bValue)));
} else if (tp.getType() == "Integer") {
int iValue = Integer.getInteger(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new IntegerType().setValue(iValue)));
} else if (tp.getType() == "Decimal") {
long lValue = Long.getLong(tp.getValue());
parameterComponents.add(new StructureMap.StructureMapGroupRuleTargetParameterComponent().setValue(new DecimalType(lValue)));
}
}
return parameterComponents;
}
public List<StructureMap.StructureMapStructureComponent> createMapStructureList() {
List<StructureMap.StructureMapStructureComponent> retVal = new ArrayList<StructureMap.StructureMapStructureComponent>();
StructureMap.StructureMapStructureComponent source = new StructureMap.StructureMapStructureComponent();
StructureMap.StructureMapStructureComponent target = new StructureMap.StructureMapStructureComponent();
source.setUrl("http://opencimi.org/structuredefinition/TestStructure");
source.setMode(StructureMap.StructureMapModelMode.SOURCE);
target.setUrl("http://hl7.org/fhir/StructureDefinition/Coding");
target.setMode(StructureMap.StructureMapModelMode.TARGET);
retVal.add(source);
retVal.add(target);
return retVal;
}
public StructureDefinition.StructureDefinitionDifferentialComponent createTestDiff() {
StructureDefinition.StructureDefinitionDifferentialComponent retVal = new StructureDefinition.StructureDefinitionDifferentialComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition.StructureDefinitionSnapshotComponent createTestSnapshot() {
StructureDefinition.StructureDefinitionSnapshotComponent retVal = new StructureDefinition.StructureDefinitionSnapshotComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
ed.setMin(1);
ed.setMax("1");
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition createTestStructure() {
StructureDefinition sd = new StructureDefinition();
sd.setId("TestStructure");
sd.setUrl("http://opencimi.org/structuredefinition/TestStructure");
sd.setStatus(Enumerations.PublicationStatus.DRAFT);
sd.setName("TestStructure");
sd.setType("TestStructure");
sd.setSnapshot(this.createTestSnapshot());
sd.setDifferential(this.createTestDiff());
sd.setKind(StructureDefinition.StructureDefinitionKind.LOGICAL);
return sd;
}
public StructureMap createTestStructuremap() throws Exception {
StructureMap retMap = new StructureMap();
retMap.setUrl("http://opencimi.org/structuremap/testtransform");
retMap.setName("TestTransform");
retMap.setStatus(Enumerations.PublicationStatus.DRAFT);
retMap.setStructure(this.createMapStructureList());
retMap.setGroup(this.buildTestGroup());
return retMap;
}
/**
* Sets up the resource paths as well as create the contexts using a defalut validator to start with.
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
if (this.context == null) {
this.context = FhirContext.forDstu3();
}
}
/**
* See #682
*/
@Test
public void testMappingTransform() throws Exception {
Map<String, StructureMap> maps = new HashMap<String, StructureMap>(); // Instantiate a hashmap for StructureMaps
this.validationSupport = new PrePopulatedValidationSupport(); // Create Validation Instance
for (StructureDefinition sd : new DefaultProfileValidationSupport().fetchAllStructureDefinitions(this.context)) { // Read in the default Structure Definitions into a validator that allows custom
// declared structure definitions.
this.validationSupport.addStructureDefinition(sd);
}
StructureDefinition sd1 = this.createTestStructure(); // Calls a method that constructs a comp
this.validationSupport.addStructureDefinition(sd1); // Add custom structure to validation support.
this.hapiContext = new HapiWorkerContext(this.context, this.validationSupport);// Init the Hapi Work
StructureMap map = this.createTestStructuremap();
maps.put(map.getUrl(), map);
StructureMapUtilities scu = new StructureMapUtilities(hapiContext, maps, null, null);
List<StructureDefinition> result = scu.analyse(null, map).getProfiles();
assertEquals(1, result.size());
ourLog.info(context.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.get(0)));
}
public class TargetParam {
private String type;
private String value;
public TargetParam(String type, String value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public String getValue() {
return value;
}
public void setType(String type) {
this.type = type;
}
public void setValue(String value) {
this.value = value;
}
}
}

View File

@ -8,7 +8,7 @@ import java.util.List;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.model.*;
import org.junit.AfterClass;
import org.junit.BeforeClass;

View File

@ -1,30 +0,0 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.eclipse" additivity="false" level="info">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.apache" additivity="false" level="info">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.thymeleaf" additivity="false" level="warn">
<appender-ref ref="STDOUT" />
</logger>
<!--
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="trace">
<appender-ref ref="STDOUT" />
</logger>
-->
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,53 @@
{
"resourceType": "MedicationRequest",
"id": "196356",
"meta": {
"versionId": "2",
"lastUpdated": "2017-08-04T15:26:29.333-04:00",
"profile": [
]
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <p>Viagra 100 mg Tablets</p>\n <p>\n <b>Creation Date: 2017-08-04</b>\n </p>\n </div>"
},
"status": "active",
"intent": "order",
"category": {
"coding": [
{
"system": "http://hl7.org/fhir/medication-request-category",
"code": "community"
}
]
},
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "316663",
"display": "Viagra"
}
]
},
"subject": {
"reference": "Patient/195975",
"display": "Mary Ann Mallady"
},
"authoredOn": "2017-08-03",
"requester": {
"agent": {
"reference": "Practitioner/196336"
}
},
"reasonCode": [
{
"coding": [
{
"system": "http://snomed.info/sct",
"code": "14760008"
}
]
}
]
}

View File

@ -0,0 +1,447 @@
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="Patient"/>
<meta>
<lastUpdated value="2017-07-14T08:37:31.190+02:00"/>
</meta>
<contained>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="1"/>
</ValueSet>
</contained>
<contained>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="2"/>
</ValueSet>
</contained>
<contained>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="3"/>
</ValueSet>
</contained>
<contained>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="4"/>
</ValueSet>
</contained>
<contained>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="5"/>
</ValueSet>
</contained>
<url value="http://www.myServer.com/fhir/StructureDefinition/Patient"/>
<version value="1.0"/>
<name value="Custom Patient"/>
<title value="Patient"/>
<status value="draft"/>
<experimental value="false"/>
<date value="2017-07-14T08:37:31+02:00"/>
<publisher value="Me"/>
<contact>
<name value="test"/>
<telecom>
<system value="email"/>
<value value="test@test.com"/>
<use value="work"/>
</telecom>
</contact>
<description value="Information about an individual receiving health care services"/>
<useContext>
<code>
<system value="urn:iso:std:iso:3166"/>
<code value="FR"/>
<display value="France"/>
</code>
</useContext>
<fhirVersion value="3.0.1"/>
<kind value="resource"/>
<abstract value="false"/>
<type value="Patient"/>
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/patient"/>
<derivation value="constraint"/>
<snapshot>
<element>
<path value="Patient"/>
</element>
<element>
<path value="Patient.id"/>
<short value="Logical id of this artifact"/>
<definition value="The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="id"/>
</type>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.meta"/>
<short value="Metadata about the resource"/>
<definition value="The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content may not always be associated with version changes to the resource."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Meta"/>
</type>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.text"/>
<max value="0"/>
</element>
<element>
<path value="Patient.contained"/>
<max value="0"/>
</element>
<element>
<path value="Patient.implicitRules"/>
<max value="0"/>
</element>
<element>
<path value="Patient.language"/>
<short value="Language of the resource content"/>
<definition value="The base language in which the resource is written."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="code"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.extension"/>
<slicing>
<discriminator>
<type value="value"/>
<path value="url"/>
</discriminator>
<rules value="open"/>
</slicing>
<definition value="May be used to represent additional information that is not part of the basic definition of the element."/>
</element>
<element>
<path value="Patient.extension"/>
<short value="identityReliabilityCode"/>
<definition value="The patient identity reliability code"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/identityReliabilityCode"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
<binding>
<strength value="required"/>
<valueSetReference>
<reference value="ValueSet/IDENTITYSTATUS"/>
</valueSetReference>
</binding>
</element>
<element>
<path value="Patient.extension"/>
<short value="lunarBirthDate"/>
<definition value="The patient lunar's birth date"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/lunarBirthDate"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.extension"/>
<short value="legalStatus"/>
<definition value="The patient legal status"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/legalStatus"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
<binding>
<strength value="required"/>
<valueSetReference>
<reference value="ValueSet/ADT_LEGALSTATUS"/>
</valueSetReference>
</binding>
</element>
<element>
<path value="Patient.extension"/>
<short value="familyStatus"/>
<definition value="The patient family status"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/familyStatus"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
<binding>
<strength value="required"/>
<valueSetReference>
<reference value="ValueSet/FAMILYSTATUS"/>
</valueSetReference>
</binding>
</element>
<element>
<path value="Patient.extension"/>
<short value="birthPlace"/>
<definition value="The patient birth place"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://hl7.org/fhir/StructureDefinition/birthPlace"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.extension"/>
<short value="homeless"/>
<definition value="The patient being homeless, true if homeless"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/homeless"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.extension"/>
<short value="phoneConsent"/>
<definition value="The patient consent on phone level"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/phoneConsent"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
<binding>
<strength value="required"/>
<valueSetReference>
<reference value="ValueSet/ADT_CONTACT_CONSENT_MOBILE"/>
</valueSetReference>
</binding>
</element>
<element>
<path value="Patient.extension"/>
<short value="emailConsent"/>
<definition value="The patient consent on email level"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/emailConsent"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
<binding>
<strength value="required"/>
<valueSetReference>
<reference value="ValueSet/ADT_CONTACT_CONSENT_EMAIL"/>
</valueSetReference>
</binding>
</element>
<element>
<path value="Patient.extension"/>
<short value="comments"/>
<definition value="The patient comments"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/comments"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.extension"/>
<short value="nationality"/>
<definition value="The patient nationality"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://hl7.org/fhir/StructureDefinition/patient-nationality"/>
</type>
<isModifier value="false"/>
</element>
<element>
<path value="Patient.identifier"/>
<short value="An identifier for this patient"/>
<definition value="An identifier for this patient."/>
<min value="0"/>
<max value="*"/>
<type>
<code value="Identifier"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/Identifier"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.active"/>
<max value="0"/>
</element>
<element>
<path value="Patient.name"/>
<short value="A name associated with the patient"/>
<definition value="A name associated with the individual."/>
<min value="0"/>
<max value="*"/>
<type>
<code value="HumanName"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/HumanName"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.telecom"/>
<short value="A contact detail for the individual"/>
<definition value="A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted."/>
<min value="0"/>
<max value="*"/>
<type>
<code value="ContactPoint"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/ContactPoint"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.gender"/>
<short value="male | female | other | unknown"/>
<definition value="Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="code"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.birthDate"/>
<short value="The date of birth for the individual"/>
<definition value="The date of birth for the individual."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="date"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.birthDate.extension"/>
<slicing>
<discriminator>
<type value="value"/>
<path value="url"/>
</discriminator>
<rules value="open"/>
</slicing>
</element>
<element>
<path value="Patient.birthDate.extension"/>
<short value="approximateBirthDate"/>
<definition value="Flag to indicate if the birthdate is approximative or not"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Extension"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/birthdate-approximative"/>
</type>
<isModifier value="false"/>
</element>
<element>
<path value="Patient.deceased[x]"/>
<short value="Indicates if the individual is deceased or not"/>
<definition value="Indicates if the individual is deceased or not."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="boolean"/>
</type>
<type>
<code value="dateTime"/>
</type>
<isModifier value="true"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.address"/>
<short value="Addresses for the individual"/>
<definition value="Addresses for the individual."/>
<min value="0"/>
<max value="*"/>
<type>
<code value="Address"/>
<profile value="http://www.myServer.com/fhir/StructureDefinition/Address"/>
</type>
<isModifier value="false"/>
<isSummary value="true"/>
</element>
<element>
<path value="Patient.maritalStatus"/>
<max value="0"/>
</element>
<element>
<path value="Patient.multipleBirth[x]"/>
<short value="Whether patient is part of a multiple birth"/>
<definition value="Indicates whether the patient is part of a multiple (bool) or indicates the actual birth order (integer)."/>
<min value="0"/>
<max value="1"/>
<type>
<code value="boolean"/>
</type>
<type>
<code value="integer"/>
</type>
<isModifier value="false"/>
<isSummary value="false"/>
</element>
<element>
<path value="Patient.photo"/>
<max value="0"/>
</element>
<element>
<path value="Patient.contact"/>
<max value="0"/>
</element>
<element>
<path value="Patient.animal"/>
<max value="0"/>
</element>
<element>
<path value="Patient.communication"/>
<max value="0"/>
</element>
<element>
<path value="Patient.generalPractitioner"/>
<max value="0"/>
</element>
<element>
<path value="Patient.managingOrganization"/>
<max value="0"/>
</element>
<element>
<path value="Patient.link"/>
<max value="0"/>
</element>
</snapshot>
</StructureDefinition>

View File

@ -0,0 +1,61 @@
{
"resourceType": "CommunicationRequest",
"id": "Christol0808",
"meta": {
"versionId": "1",
"lastUpdated": "2017-09-09T13:40:35.438-04:00"
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Request for Encounter 08082017 Report</div>"
},
"extension": [
{
"url": "http://hl7.org/fhir/us/attachments/StructureDefinition/attachment-type",
"valueCodeableConcept": {
"coding": [
{
"system": "http://loinc.org",
"code": "34133-1",
"display": "Summarization of Encounter Note 08082017"
}
]
}
}
],
"identifier": [
{
"system": "http://www.jurisdiction.com/insurer/123456",
"value": "AnthemChristol08082017",
"_value": {
"fhir_comments": [
" this is the value to which the response will refer "
]
}
}
],
"basedOn": [
{
"reference": "Claim/good-health-claim-1"
}
],
"status": "active",
"subject": {
"reference": "Patient/good-health-patient-1"
},
"recipient": [
{
"reference": "Organization/good-health"
}
],
"payload": [
{
"contentString": "Please provide the summarization of encounter note. "
}
],
"occurrenceDateTime": "2017-09-09T08:01:10-08:00",
"authoredOn": "2017-09-09T08:01:10-08:00",
"sender": {
"reference": "Organization/example-payer"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,455 @@
<QuestionnaireResponse xmlns="http://hl7.org/fhir">
<identifier>
<value value="1234567890"/>
</identifier>
<questionnaire>
<reference value="Questionnaire/q_jon"/>
</questionnaire>
<status value="completed"/>
<subject>
<reference value="http://fhirtest.uhn.ca/baseDstu3/Patient/proband"/>
</subject>
<author>
<reference value="http://fhirtest.uhn.ca/baseDstu3/Practitioner/f007"/>
</author>
<authored value="2016-01-08"/>
<item>
<linkId value="root"/>
<item>
<linkId value="g1"/>
<text value="CLINICAL INFORMATION"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="1.1"/>
</extension>
<linkId value="1.1"/>
<text value="Patient Clinical Information"/>
<answer>
<valueString value="Previous chest X-RAY was suspicious. Heavy smoker, 15 pack years."/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="1.2"/>
</extension>
<linkId value="1.2"/>
<text value="Previous Examination (Date and Modality)"/>
<answer>
<valueString value="Chest XR - September 23, 2015"/>
</answer>
</item>
</item>
<item>
<linkId value="g2"/>
<text value="IMAGING PROCEDURE DESCRIPTION"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="2.1"/>
</extension>
<linkId value="2.1"/>
<text value="Overall Image Quality:"/>
<answer>
<valueCoding>
<code value="2.1a"/>
<display value="Adequate"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="2.2"/>
</extension>
<linkId value="2.2"/>
<text value="Intravenous Contrast Used?"/>
<answer>
<valueBoolean value="false"/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="2.3"/>
</extension>
<linkId value="2.3"/>
<text value="Additional Comments"/>
<answer>
<valueString value="n/a."/>
</answer>
</item>
</item>
<item>
<linkId value="g3"/>
<text value="FINDINGS"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3"/>
</extension>
<linkId value="g3.0"/>
<text value="T Category"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.1"/>
</extension>
<linkId value="g3.1"/>
<text value="Location of Main Nodule/Mass (Primary tumor, or Reference tumor)"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.1.1"/>
</extension>
<linkId value="q3.1.1"/>
<text value="Location of main nodule/mass:"/>
<answer>
<valueCoding>
<code value="3.1.1a"/>
<display value="Peripheral"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.1.2"/>
</extension>
<linkId value="3.1.2"/>
<answer>
<valueString value="Right Upper Lung, Posterior segment."/>
</answer>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.2"/>
</extension>
<linkId value="g3.2"/>
<text value="Size and characteristics of main nodule/mass"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.2.1"/>
</extension>
<linkId value="3.2.1"/>
<text value="Size of the nodule/mass:"/>
<answer>
<valueCoding>
<code value="3.2.1a"/>
<display value="Solid nodule/mass"/>
</valueCoding>
</answer>
<item><!-- Measurement, image, series, etc for all 3 answer choices goes here. Conditonal. -->
<linkId value="g3.2.1"/>
<item><!-- Group for answer choice a -->
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen"><!-- Note that this extension is at the group level. -->
<extension url="#question">
<valueString value="3.2.1"/>
</extension>
<extension url="#answer">
<valueCoding>
<code value="3.2.1a"/>
</valueCoding>
</extension>
</extension>
<linkId value="g3.2.1a"/>
<item>
<linkId value="3.2.1a"/>
<text value="largest dimension:"/>
<answer>
<valueInteger value="20"/>
</answer>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl">
<valueCodeableConcept>
<coding>
<system value="http://hl7.org/fhir/ValueSet/questionnaire-item-control"/>
<code value="unit"/>
</coding>
</valueCodeableConcept>
</extension>
<text value="mm"/>
</item>
</item>
<item>
<linkId value="3.2.1a.image"/>
<text value="image"/>
<answer>
<valueString value="32"/>
</answer>
</item>
<item>
<linkId value="3.2.1a.series"/>
<text value="series"/>
<answer>
<valueString value="3"/>
</answer>
</item>
</item>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.2.2"/>
</extension>
<linkId value="3.2.2"/>
<text value="Plane in which the mass was measured:"/>
<answer>
<valueCoding>
<code value="3.2.2a"/>
<display value="Axial"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.2.3"/>
</extension>
<linkId value="3.2.3"/>
<answer>
<valueString value="Solid attenuation of mass, margins spiculated."/>
</answer>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.3"/>
</extension>
<linkId value="g3.3"/>
<text value="Structures directly involved"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.3.1"/>
</extension>
<linkId value="3.3.1"/>
<text value="State if there is bronchial involvement:"/>
<answer>
<valueCoding>
<code value="3.3.1b"/>
<display value="No"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.3.2"/>
</extension>
<linkId value="3.3.2"/>
<text value="Is there direct involvement of any other anatomical structures?"/>
<answer>
<valueBoolean value="false"/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.3.3"/>
</extension>
<linkId value="3.3.3"/>
<text value="Are there additional suspicious pulmonary nodules?"/>
<answer>
<valueBoolean value="false"/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="3.3.4"/>
</extension>
<linkId value="3.3.4"/>
<text value="Other notable intrathoracic findings (eg lymphangitis carcinomatosis):"/>
<answer>
<valueString value="n/a"/>
</answer>
</item>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="4"/>
</extension>
<linkId value="4.0"/>
<text value="N Category"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="4.1"/>
</extension>
<linkId value="4.1"/>
<text value="Are there enlarged lymph nodes?"/>
<answer>
<valueBoolean value="false"/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="4.2"/>
</extension>
<linkId value="4.2"/>
<text value="Other notable findings:"/>
<answer>
<valueString value="Liner / scar atelectasis lingua, anterior segment of right upper lobe and bilateral lower lobes."/>
</answer>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="5"/>
</extension>
<linkId value="5.0"/>
<text value="M Category (Suspicious Extrathoracic Findings (M1b))"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="5.1"/>
</extension>
<linkId value="5.1"/>
<text value="Are there suspicious extrathoracic findings?"/>
<answer>
<valueBoolean value="true"/>
</answer>
<item>
<linkId value="g5.1.yes"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen">
<extension url="#question">
<valueString value="5.1"/>
</extension>
<extension url="#answer">
<valueBoolean value="true"/>
</extension>
</extension>
<linkId value="5.1.yes"/>
<text value="Applicable Structures and Descriptions:"/>
<answer>
<valueCoding>
<code value="5.1.yes.d"/>
<display value="Other"/>
</valueCoding>
</answer>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen">
<extension url="#question">
<valueString value="5.1.yes"/>
</extension>
<extension url="#answer">
<valueCoding>
<code value="5.1.yes.d"/>
</valueCoding>
</extension>
</extension>
<linkId value="5.1.yes.d.description"/>
<text value="Description of structures:"/>
<answer>
<valueString value="3 cm calcified thyroid nodule on TUL left."/>
</answer>
</item>
</item>
</item>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="6"/>
</extension>
<linkId value="6.0"/>
<text value="Additional Findings"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="6.1"/>
</extension>
<linkId value="6.1"/>
<text value="Are there additional findings?"/>
<answer>
<valueBoolean value="true"/>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="6.2"/>
</extension>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen">
<extension url="#question">
<valueString value="6.1"/>
</extension>
<extension url="#answer">
<valueBoolean value="true"/>
</extension>
</extension>
<linkId value="6.2"/>
<text value="Findings and Descriptions:"/>
<answer>
<valueString value="Oligemic changes in right upper lobe from possible old pulmonary embolus."/>
</answer>
</item>
</item>
</item>
<item>
<linkId value="g7"/>
<text value="IMPRESSIONS"/>
<item>
<linkId value="g7.1"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="7.1"/>
</extension>
<linkId value="7.1"/>
<text value="Impression/Summary:"/>
<answer>
<valueString value="Spiculated mass in posterior segment of right upper lobe that has increasing size from 16 to 20 mm."/>
</answer>
</item>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="7.2"/>
</extension>
<linkId value="g7.2"/>
<text value="Radiologic Staging (TNM Version 7th edition)"/>
<item>
<linkId value="g7.20"/>
<text value="If this is a biopsy proven carcinoma, the preliminary radiologic stage is:"/>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="i)"/>
</extension>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-questionControl" >
<valueCodeableConcept>
<coding>
<code value="radio-button"/>
<display value="Radio Button"/>
</coding>
</valueCodeableConcept>
</extension>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation" >
<valueCode value="horizontal"/>
</extension>
<linkId value="7.2i"/>
<text value="Primary Tumour (T):"/>
<answer>
<valueCoding>
<code value="T1a"/>
<display value="T1a"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="ii)"/>
</extension>
<linkId value="7.2ii"/>
<text value="Regional Lymph Nodes (N):"/>
<answer>
<valueCoding>
<code value="N0"/>
<display value="N0"/>
</valueCoding>
</answer>
</item>
<item>
<extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-label">
<valueString value="iii)"/>
</extension>
<linkId value="7.2iii"/>
<text value="Distant Metastasis (M):"/>
<answer>
<valueCoding>
<code value="M0"/>
<display value="M0"/>
</valueCoding>
</answer>
</item>
</item>
</item>
</item>
</item>
</QuestionnaireResponse>

View File

@ -0,0 +1,298 @@
{
"resourceType": "TestScript",
"id": "search",
"text": {
"status": "generated",
"div": "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: search</p><p><b>name</b>: Read, Search and Conditional Create and Delete</p><p><b>description</b>: Test Script for testing search, read, and conditional create and delete</p><h3>Fixtures</h3><table><tr><td>-</td><td><b>Resource</b></td></tr><tr><td>*</td><td><a>Patient/patient-example.xml</a></td></tr></table><blockquote><p><b>variable</b></p><p><b>name</b>: V1</p><p><b>sourceId</b>: R1</p><p><b>headerField</b>: Location</p></blockquote><blockquote><p><b>variable</b></p><p><b>name</b>: V2</p><p><b>sourceId</b>: R3</p><p><b>path</b>: fhir:Patient/fhir:name/fhir:given/@value</p></blockquote><blockquote><p><b>setup</b></p><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td><td><b>Type</b></td><td><b>Resource</b></td><td><b>Params</b></td></tr><tr><td>*</td><td>delete</td><td>Patient</td><td>given=John&amp;family=Doe</td></tr></table></blockquote></blockquote><blockquote><p><b>test</b></p><p><b>name</b>: Create</p><p><b>description</b>: Create, read, search, conditional create, conditional delete.</p><blockquote><p><b>metadata</b></p><h3>Links</h3><table><tr><td>-</td><td><b>Url</b></td><td><b>Description</b></td></tr><tr><td>*</td><td><a>http://hl7.org/implement/standards/FHIR-Develop/patient.html</a></td><td>FHIR Patient</td></tr></table><blockquote><p><b>operation</b></p><p><b>type</b>: create</p><p><b>resource</b>: Patient</p><p><b>description</b>: Conditional Create Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.13.1</a></p><p><b>required</b>: true</p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: delete</p><p><b>resource</b>: Patient</p><p><b>description</b>: Conditional Delete Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.12.1</a></p><p><b>required</b>: true</p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: read</p><p><b>resource</b>: Patient</p><p><b>description</b>: Patient Read Operation</p><p><b>link</b>: <a>http://hl7.org/implement/standards/FHIR-Develop/http.html#read</a></p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: search</p><p><b>resource</b>: Patient</p><p><b>description</b>: Patient Search Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.14</a></p><p><b>validated</b>: true</p></blockquote></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote></blockquote></div>"
},
"url": "http://hl7.org/fhir/TestScript/search",
"name": "Read, Search and Conditional Create and Delete",
"status": "draft",
"description": "Test Script for testing search, read, and conditional create and delete",
"metadata": {
"capability": [
{
"required": true,
"description": "Patient Create and Read Operations",
"link": [
"http://hl7.org/implement/standards/FHIR-Develop/http.html#create",
"http://hl7.org/implement/standards/FHIR-Develop/http.html#read"
],
"conformance": {
"reference": "Conformance/example"
}
},
{
"required": true,
"description": "Patient Conditional Delete Operation",
"link": [
"http://hl7-fhir.github.io/http.html#2.1.0.12.1"
],
"conformance": {
"reference": "Conformance/example"
}
},
{
"required": true,
"description": "Patient Conditional Create Operation",
"link": [
"http://hl7-fhir.github.io/http.html#2.1.0.13.1"
],
"conformance": {
"reference": "Conformance/example"
}
}
]
},
"fixture": [
{
"id": "example-patient",
"resource": {
"reference": "Patient/example"
}
}
],
"variable": [
{
"name": "V1",
"headerField": "Location",
"sourceId": "R1"
},
{
"name": "V2",
"path": "fhir:Patient/fhir:name/fhir:given/@value",
"sourceId": "R3"
},
{
"name": "DefaultValue",
"defaultValue": "Replace at Runtime"
}
],
"setup": {
"action": [
{
"fhir_comments": [
" Conditional Delete "
],
"operation": {
"type": {
"code": "delete"
},
"resource": "Patient",
"params": "given=John&family=Doe"
}
}
]
},
"test": [
{
"id": "Test1",
"name": "Create",
"description": "Create, read, search, conditional create, conditional delete.",
"metadata": {
"link": [
{
"url": "http://hl7.org/implement/standards/FHIR-Develop/patient.html",
"description": "FHIR Patient"
}
],
"capability": [
{
"validated": true,
"description": "Patient Search Operation",
"link": [
"http://hl7.org/implement/standards/FHIR-Develop/http.html#search"
],
"conformance": {
"reference": "Conformance/example"
}
}
]
},
"action": [
{
"fhir_comments": [
" Create the patient using fixture "
],
"operation": {
"type": {
"code": "create"
},
"sourceId": "example-patient"
}
},
{
"assert": {
"responseCode": "201"
}
},
{
"fhir_comments": [
" Patient search by name. Save the responseBody in 'F1' fixture.\n\t\t\t\tSave the responseHeader in H1 "
],
"operation": {
"type": {
"code": "search"
},
"resource": "Patient",
"contentType": "json",
"params": "?given=John&family=Doe",
"responseId": "R1"
}
},
{
"fhir_comments": [
" Verify that the Location in response-header is valid "
],
"assert": {
"headerField": "Location",
"operator": "notEmpty",
"warningOnly": true
}
},
{
"fhir_comments": [
" Verify that the birthdate got persisted and is being returned properly "
],
"assert": {
"operator": "equals",
"path": "fhir:Patient/fhir:birthDate/@value",
"sourceId": "R1",
"value": "1974-12-31"
}
},
{
"fhir_comments": [
" Verify that the navigation links are valid "
],
"assert": {
"navigationLinks": true,
"warningOnly": true
}
},
{
"fhir_comments": [
" Use the Location returned earlier to grab the resource\n\t\t \t\tto verify that Location was pointing to correct resource. "
],
"operation": {
"type": {
"code": "search"
},
"accept": "json",
"responseId": "R2",
"url": "${V1}"
}
},
{
"assert": {
"contentType": "json"
}
},
{
"assert": {
"response": "okay"
}
},
{
"fhir_comments": [
" Search for the resource but this time using the birthdate\n\t\t\t\tas a search parameter to make sure search by birthDate works "
],
"operation": {
"type": {
"code": "search"
},
"resource": "Patient",
"accept": "json",
"params": "?given=John&family=Doe&birthdate=1974-12-31",
"responseId": "R3"
}
},
{
"assert": {
"contentType": "json"
}
},
{
"assert": {
"response": "okay"
}
},
{
"fhir_comments": [
" Verify that the birthDate matches expectations "
],
"assert": {
"compareToSourceId": "R2",
"compareToSourcePath": "fhir:Patient/fhir:birthDate/@value",
"path": "fhir:Patient/fhir:birthDate/@value",
"sourceId": "R3"
}
},
{
"fhir_comments": [
" Verify that the name matches expectations "
],
"assert": {
"path": "fhir:Patient/fhir:name/fhir:given/@value",
"sourceId": "R3",
"value": "John"
}
},
{
"fhir_comments": [
" Conditional Create "
],
"operation": {
"type": {
"code": "create"
},
"requestHeader": [
{
"field": "If-None-Exist",
"value": "Patient?given=John&Doe&birthdate=1974-12-31"
}
],
"sourceId": "F1"
}
},
{
"fhir_comments": [
" The response code of 200 verifies that the resource\n\t\t\t\talready exists and did not get created "
],
"assert": {
"responseCode": "200"
}
},
{
"fhir_comments": [
" Conditional Delete "
],
"operation": {
"type": {
"code": "delete"
},
"resource": "Patient",
"params": "?given=John&family=Doe&birthdate=1974-12-31"
}
},
{
"fhir_comments": [
" Search again and make sure the patient has been deleted.\n\t\t \t\t This time perform read by id using variable "
],
"operation": {
"type": {
"code": "read"
},
"resource": "Patient",
"params": "/${V2}"
}
},
{
"assert": {
"responseCode": "410"
}
}
]
}
]
}

View File

@ -361,6 +361,15 @@
the returned
<![CDATA[<code>Location</code>]]> header value as well
</action>
<action type="add">
A new flag has been add to the CLI upload-definitions command
"-e" which allows skipping particular resources
</action>
<action type="add">
An issue in JPA server has been corrected where if a CodeSystem
resource was deleted, it was not possible to create a new resource
with the same URI as the previous one
</action>
</release>
<release version="2.5" date="2017-06-08">
<action type="fix">