diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidateCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidateCommand.java
index 3d652730a79..2015e98f2e0 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidateCommand.java
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidateCommand.java
@@ -35,6 +35,7 @@ import org.apache.commons.cli.ParseException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.fusesource.jansi.Ansi.Color;
+import org.hl7.fhir.common.hapi.validation.support.NpmPackageValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
@@ -149,21 +150,25 @@ public class ValidateCommand extends BaseCommand {
}
if (theCommandLine.hasOption("p")) {
+ ValidationSupportChain validationSupportChain;
switch (ctx.getVersion().getVersion()) {
case DSTU2: {
FhirInstanceValidator instanceValidator;
- ValidationSupportChain validationSupportChain =
+ validationSupportChain =
ValidationSupportChainCreator.getValidationSupportChainDstu2(ctx, theCommandLine);
+ validationSupportChain.oneCodingIsSufficient = true;
instanceValidator = new FhirInstanceValidator(validationSupportChain);
val.registerValidatorModule(instanceValidator);
break;
}
case DSTU3:
case R4: {
+ ourLog.info("Adding FHIR R4 validation support chain");
FhirInstanceValidator instanceValidator = new FhirInstanceValidator(ctx);
val.registerValidatorModule(instanceValidator);
- ValidationSupportChain validationSupportChain =
+ validationSupportChain =
ValidationSupportChainCreator.getValidationSupportChainR4(ctx, theCommandLine);
+ validationSupportChain.oneCodingIsSufficient = true;
instanceValidator.setValidationSupport(validationSupportChain);
break;
}
@@ -171,6 +176,21 @@ public class ValidateCommand extends BaseCommand {
throw new ParseException(
Msg.code(1620) + "Profile validation (-p) is not supported for this FHIR version");
}
+
+ // If they want to do profile validation - there might be a whole IG to load...
+ if (theCommandLine.hasOption("igpack")) {
+ String igPack = theCommandLine.getOptionValue("igpack");
+ ourLog.info("Loading IG Package from {} to the validation support chain", igPack);
+ try {
+ NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(ctx);
+ npmPackageSupport.loadPackageFromFile(igPack);
+ validationSupportChain.addValidationSupport(0, npmPackageSupport);
+ } catch (IOException iox) {
+ throw new ParseException(
+ Msg.code(1620) + "IGpack validation (--igpack) failed: " + iox.getMessage());
+ }
+ ourLog.info("Completed loading IG Package from {}", igPack);
+ }
}
val.setValidateAgainstStandardSchema(theCommandLine.hasOption("x"));
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.java
index fa409f5f93b..6c560d2a045 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.java
@@ -3,13 +3,14 @@ package org.hl7.fhir.common.hapi.validation.support;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.LenientErrorHandler;
-import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ClasspathUtil;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.npm.NpmPackage;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@@ -31,11 +32,16 @@ public class NpmPackageValidationSupport extends PrePopulatedValidationSupport {
super(theFhirContext);
}
+ @Override
+ public String getName() {
+ return getFhirContext().getVersion().getVersion() + " NPM Package Validation Support";
+ }
+
/**
* Load an NPM package using a classpath specification, e.g. /path/to/resource/my_package.tgz
. The
* classpath spec can optionally be prefixed with the string classpath:
*
- * @throws InternalErrorException If the classpath file can't be found
+ * @throws IOException If the classpath file can't be found
*/
public void loadPackageFromClasspath(String theClasspath) throws IOException {
try (InputStream is = ClasspathUtil.loadResourceAsStream(theClasspath)) {
@@ -47,6 +53,21 @@ public class NpmPackageValidationSupport extends PrePopulatedValidationSupport {
}
}
+ /**
+ * Load an NPM package from the filesystem e.g. my_package.tgz
.
+ *
+ * @throws IOException If the package file can't be found
+ */
+ public void loadPackageFromFile(String theFile) throws IOException {
+ File inFile = new File(theFile);
+ InputStream is = new FileInputStream(inFile);
+ NpmPackage pkg = NpmPackage.fromPackage(is);
+ if (pkg.getFolders().containsKey("package")) {
+ loadResourcesFromPackage(pkg);
+ loadBinariesFromPackage(pkg);
+ }
+ }
+
private void loadResourcesFromPackage(NpmPackage thePackage) {
NpmPackage.NpmPackageFolder packageFolder = thePackage.getFolders().get("package");
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java
index 4eea50efc11..789fcc0ee02 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java
@@ -371,12 +371,13 @@ public class ValidationSupportChain implements IValidationSupport {
if (retVal != null) {
if (ourLog.isDebugEnabled()) {
ourLog.debug(
- "Code {}|{} '{}' in ValueSet {} validated by {}",
+ "Code {}|{} '{}' in ValueSet {} validated by {} result: {}",
theCodeSystem,
theCode,
theDisplay,
theValueSetUrl,
- next.getName());
+ next.getName(),
+ retVal.getMessage() != null ? retVal.getMessage() : "Success");
}
return retVal;
}
@@ -401,12 +402,13 @@ public class ValidationSupportChain implements IValidationSupport {
if (retVal != null) {
if (ourLog.isDebugEnabled()) {
ourLog.debug(
- "Code {}|{} '{}' in ValueSet {} validated by {}",
+ "Code {}|{} '{}' in ValueSet {} validated by {} result: {}",
theCodeSystem,
theCode,
theDisplay,
theValueSet.getIdElement(),
- next.getName());
+ next.getName(),
+ retVal.getMessage() != null ? retVal.getMessage() : "Success");
}
return retVal;
}
@@ -445,4 +447,18 @@ public class ValidationSupportChain implements IValidationSupport {
}
return null;
}
+ /**
+ * See VersionSpecificWorkerContextWrapper#validateCode in hapi-fhir-validation.
+ *
+ * If true, validation for codings will return a positive result if AT LEAST ONE coding is valid. + * If false, validation for codings will return a positive result if there is ALL codings are valid. + *
+ * @return if the application has configured validation to use logical AND, as opposed to logical OR, which is the default + */ + public boolean oneCodingIsSufficient = false; // default value from parent Interface (it's the wrong way round !!!) + + @Override + public boolean isEnabledValidationForCodingsLogicalAnd() { // should be named ....LogicalAny + return oneCodingIsSufficient; + } }