res = new ArrayList<>();
if (folder != null) {
- for (File f : folder.listFiles()) {
- if (!f.isDirectory() && !Utilities.existsInList(f.getName(), "package.json", ".index.json", ".index.db", ".oids.json", ".oids.db")) {
- res.add(f.getName());
+ if (folder.exists()) {
+ for (File f : folder.listFiles()) {
+ if (!f.isDirectory() && !Utilities.existsInList(f.getName(), "package.json", ".index.json", ".index.db", ".oids.json", ".oids.db")) {
+ res.add(f.getName());
+ }
}
}
} else {
@@ -648,7 +650,17 @@ public class NpmPackage {
}
-
+ /**
+ * Create a package .index.json file for a package folder.
+ *
+ * See the FHIR specification for details on .index.json
+ * format and usage.
+ *
+ * @param desc
+ * @param folder
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
public void indexFolder(String desc, NpmPackageFolder folder) throws FileNotFoundException, IOException {
List remove = new ArrayList<>();
NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder();
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
index 2e9a45283..225bdd409 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
@@ -31,18 +31,19 @@ public class PackageHacker {
public static void main(String[] args) throws FileNotFoundException, IOException {
// new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir"));
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz");
- new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz");
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
-// new PackageHacker().edit(args[0]);
+// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v311/package.tgz", "http://hl7.org/fhir/us/core/STU3.1.1");
+ new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
}
// private void massEdit(File dir) throws IOException {
@@ -91,7 +92,7 @@ public class PackageHacker {
// }
// }
- private void edit(String name) throws FileNotFoundException, IOException {
+ private void edit(String name, String path) throws FileNotFoundException, IOException {
File f = ManagedFileAccess.file(name);
if (!f.exists())
throw new Error("Unable to find "+f.getAbsolutePath());
@@ -107,15 +108,15 @@ public class PackageHacker {
System.out.println("Altering Package "+f.getAbsolutePath());
System.out.println(nice(pck.getNpm()));
- if (change(pck.getNpm())) {
+ if (change(pck.getNpm(), path)) {
System.out.println("Revised Package");
System.out.println("=======================");
System.out.println(nice(pck.getNpm()));
System.out.println("=======================");
-// System.out.print("save? y/n: ");
-// int r = System.in.read();
-// if (r == 'y') {
+ System.out.print("save? y/n: ");
+ int r = System.in.read();
+ if (r == 'y') {
f.renameTo(ManagedFileAccess.file(Utilities.changeFileExt(name, ".tgz.bak")));
FileOutputStream fso = ManagedFileAccess.outStream(f);
try {
@@ -123,7 +124,7 @@ public class PackageHacker {
} finally {
fso.close();
}
-// }
+ }
}
}
@@ -142,13 +143,15 @@ public class PackageHacker {
return JsonParser.compose(json, true);
}
- private boolean change(JsonObject npm) throws FileNotFoundException, IOException {
- // fixVersions(npm, ver);
- if (npm.has("notForPublication")) {
- npm.remove("notForPublication");
- return true;
- }
- return false;
+ private boolean change(JsonObject npm, String path) throws FileNotFoundException, IOException {
+ npm.remove("url");
+ npm.add("url", path);
+ return true;
+// if (npm.has("notForPublication")) {
+// npm.remove("notForPublication");
+// return true;
+// }
+// return false;
}
private void fixVersionInContent(Map content) {
diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java
index 96754c2b8..eba7b198a 100644
--- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java
+++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java
@@ -1,22 +1,25 @@
package org.hl7.fhir.utilities.npm;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
+import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
-import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.EnabledOnOs;
@@ -100,7 +103,6 @@ public class FilesystemPackageManagerTests {
@DisabledOnOs(OS.WINDOWS)
public void testSystemCacheDirectory() throws IOException {
File folder = new FilesystemPackageCacheManager.Builder().withSystemCacheFolder().getCacheFolder();
-
assertEquals( "/var/lib/.fhir/packages", folder.getAbsolutePath());
}
@@ -124,6 +126,118 @@ public class FilesystemPackageManagerTests {
return params.stream();
}
+ private void createDummyTemp(File cacheDirectory, String lowerCase) throws IOException {
+ createDummyPackage(cacheDirectory, lowerCase);
+ }
+
+ private void createDummyPackage(File cacheDirectory, String packageName, String packageVersion) throws IOException {
+ String directoryName = packageName + "#" + packageVersion;
+ createDummyPackage(cacheDirectory, directoryName);
+ }
+
+ private static void createDummyPackage(File cacheDirectory, String directoryName) throws IOException {
+ File packageDirectory = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), directoryName);
+ packageDirectory.mkdirs();
+
+ File dummyContentFile = ManagedFileAccess.file(packageDirectory.getAbsolutePath(), "dummy.txt");
+ FileWriter wr = new FileWriter(dummyContentFile);
+ wr.write("Ain't nobody here but us chickens");
+ wr.flush();
+ wr.close();
+ }
+
+ private void assertThatDummyTempExists(File cacheDirectory, String dummyTempPackage) throws IOException {
+ File dummyTempDirectory = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), dummyTempPackage);
+ assertThat(dummyTempDirectory).exists();
+
+ File dummyContentFile = ManagedFileAccess.file(dummyTempDirectory.getAbsolutePath(), "dummy.txt");
+ assertThat(dummyContentFile).exists();
+ }
+
+ @Test
+ public void testCreatesIniIfDoesntExistAndCacheStaysIntact() throws IOException {
+ File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest"));
+ File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini");
+
+ createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3");
+
+ String dummyTempPackage = UUID.randomUUID().toString().toLowerCase();
+ createDummyTemp(cacheDirectory, dummyTempPackage);
+ assertThatDummyTempExists(cacheDirectory, dummyTempPackage);
+
+ assertThat(cacheIni).doesNotExist();
+ FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build();
+ assertInitializedTestCacheIsValid(cacheDirectory, true);
+ }
+
+
+
+ @Test
+ public void testClearsCacheIfVersionIsWrong() throws IOException {
+ File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest"));
+ File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini");
+
+ createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3");
+ String dummyTempPackage = UUID.randomUUID().toString().toLowerCase();
+ createDummyTemp(cacheDirectory, dummyTempPackage);
+ assertThatDummyTempExists(cacheDirectory, dummyTempPackage);
+
+
+ IniFile ini = new IniFile(cacheIni.getAbsolutePath());
+ ini.setStringProperty("cache", "version", "2", null);
+ ini.save();
+
+ assertThat(cacheIni).exists();
+ FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build();
+ assertInitializedTestCacheIsValid(cacheDirectory, false);
+ }
+
+ @Test
+ public void testCacheStaysIntactIfVersionIsTheSame() throws IOException {
+ File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest"));
+ File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini");
+
+ createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3");
+ String dummyTempPackage = UUID.randomUUID().toString().toLowerCase();
+ createDummyTemp(cacheDirectory, dummyTempPackage);
+ assertThatDummyTempExists(cacheDirectory, dummyTempPackage);
+
+
+ IniFile ini = new IniFile(cacheIni.getAbsolutePath());
+ ini.setStringProperty("cache", "version", "3", null);
+ ini.save();
+
+ assertThat(cacheIni).exists();
+ FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build();
+ assertInitializedTestCacheIsValid(cacheDirectory, true);
+ }
+
+ private void assertInitializedTestCacheIsValid(File cacheDirectory, boolean dummyPackageShouldExist) throws IOException {
+ assertThat(cacheDirectory).exists();
+ File iniFile = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini");
+ assertThat(ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini")).exists();
+ IniFile ini = new IniFile(iniFile.getAbsolutePath());
+ String version = ini.getStringProperty("cache", "version");
+ assertThat(version).isEqualTo("3");
+
+ File[] files = cacheDirectory.listFiles();
+ if (dummyPackageShouldExist) {
+ // Check that only packages.ini and our dummy package are in the cache. Our previous temp should be deleted.
+ assertThat(files).hasSize(2); // packages.ini and example.fhir.uv.myig#1.2.3 (directory)
+
+ File dummyPackage = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "example.fhir.uv.myig#1.2.3");
+ assertThat(dummyPackage).exists();
+
+ File dummyContentFile = ManagedFileAccess.file(dummyPackage.getAbsolutePath(), "dummy.txt");
+ assertThat(dummyContentFile).exists();
+ } else {
+ // Check that only packages.ini is in the cache.
+ assertThat(files).hasSize(1);
+ }
+
+
+ }
+
@MethodSource("packageCacheMultiThreadTestParams")
@ParameterizedTest
public void packageCacheMultiThreadTest(final int threadTotal, final int packageCacheManagerTotal) throws IOException {
diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml
index f0907cd29..54e5ebfa8 100644
--- a/org.hl7.fhir.validation.cli/pom.xml
+++ b/org.hl7.fhir.validation.cli/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
org.hl7.fhir.core
- 6.3.24-SNAPSHOT
+ 6.3.26-SNAPSHOT
../pom.xml
diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml
index 9bf7272b5..10e3221ea 100644
--- a/org.hl7.fhir.validation/pom.xml
+++ b/org.hl7.fhir.validation/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
org.hl7.fhir.core
- 6.3.24-SNAPSHOT
+ 6.3.26-SNAPSHOT
../pom.xml
@@ -119,37 +119,6 @@
true
-
-
- info.cqframework
- cql
- ${info_cqframework_version}
-
-
- info.cqframework
- model
- ${info_cqframework_version}
-
-
- info.cqframework
- elm
- ${info_cqframework_version}
-
-
- info.cqframework
- cql-to-elm
- ${info_cqframework_version}
-
-
- info.cqframework
- quick
- ${info_cqframework_version}
-
-
- info.cqframework
- qdm
- ${info_cqframework_version}
-
com.squareup.okhttp3
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java
index a242ca2e9..9bf88787c 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java
@@ -226,6 +226,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
@Getter @Setter private boolean allowDoubleQuotesInFHIRPath;
@Getter @Setter private boolean checkIPSCodes;
@Getter @Setter private BestPracticeWarningLevel bestPracticeLevel;
+ @Getter @Setter private boolean unknownCodeSystemsCauseErrors;
@Getter @Setter private Locale locale;
@Getter @Setter private List igs = new ArrayList<>();
@Getter @Setter private List extensionDomains = new ArrayList<>();
@@ -289,6 +290,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
fhirPathEngine = other.fhirPathEngine;
igLoader = other.igLoader;
jurisdiction = other.jurisdiction;
+ unknownCodeSystemsCauseErrors = other.unknownCodeSystemsCauseErrors;
}
/**
@@ -906,6 +908,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (policyAdvisor != null) {
validator.setPolicyAdvisor(policyAdvisor);
}
+ validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors);
return validator;
}
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java
index f719f029b..79c604c6c 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java
@@ -163,6 +163,9 @@ public class CliContext {
@JsonProperty("bestPracticeLevel")
private BestPracticeWarningLevel bestPracticeLevel = BestPracticeWarningLevel.Warning;
+ @JsonProperty("unknownCodeSystemsCauseErrors")
+ private boolean unknownCodeSystemsCauseErrors;
+
@JsonProperty("baseEngine")
public String getBaseEngine() {
return baseEngine;
@@ -832,6 +835,7 @@ public class CliContext {
Objects.equals(watchMode, that.watchMode) &&
Objects.equals(bestPracticeLevel, that.bestPracticeLevel) &&
Objects.equals(watchScanDelay, that.watchScanDelay) &&
+ Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) &&
Objects.equals(watchSettleTime, that.watchSettleTime) ;
}
@@ -839,8 +843,8 @@ public class CliContext {
public int hashCode() {
return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT,
- targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars, watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel,
- htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
+ targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars,
+ watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
}
@Override
@@ -899,6 +903,7 @@ public class CliContext {
", bestPracticeLevel=" + bestPracticeLevel +
", watchSettleTime=" + watchSettleTime +
", watchScanDelay=" + watchScanDelay +
+ ", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
'}';
}
@@ -956,4 +961,17 @@ public class CliContext {
return this;
}
+
+ @JsonProperty("unknownCodeSystemsCauseErrors")
+ public boolean isUnknownCodeSystemsCauseErrors() {
+ return unknownCodeSystemsCauseErrors;
+ }
+
+
+ @JsonProperty("unknownCodeSystemsCauseErrors")
+ public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) {
+ this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
+ }
+
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java
index fcdea6386..61d4b7d5f 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java
@@ -581,6 +581,7 @@ public class ValidationService {
}
validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
+ validationEngine.setUnknownCodeSystemsCauseErrors(cliContext.isUnknownCodeSystemsCauseErrors());
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
validationEngine.prepare(); // generate any missing snapshots
System.out.println(" go (" + timeTracker.milestone() + ")");
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java
index 23136344d..0983d0072 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java
@@ -94,8 +94,7 @@ public class Params {
public static final String DISABLE_DEFAULT_RESOURCE_FETCHER = "-disable-default-resource-fetcher";
public static final String CHECK_IPS_CODES = "-check-ips-codes";
public static final String BEST_PRACTICE = "-best-practice";
-
-
+ public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors";
public static final String RUN_TESTS = "-run-tests";
@@ -320,6 +319,8 @@ public class Params {
cliContext.setCrumbTrails(true);
} else if (args[i].equals(FOR_PUBLICATION)) {
cliContext.setForPublication(true);
+ } else if (args[i].equals(UNKNOWN_CODESYSTEMS_CAUSE_ERROR)) {
+ cliContext.setUnknownCodeSystemsCauseErrors(true);
} else if (args[i].equals(VERBOSE)) {
cliContext.setCrumbTrails(true);
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java
index 071efc120..302bc448d 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java
@@ -46,7 +46,7 @@ import javax.annotation.Nonnull;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.fhir.ucum.Decimal;
-import org.hl7.elm.r1.Code;
+
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException;
@@ -598,6 +598,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean example ;
private IDigitalSignatureServices signatureServices;
private ContextUtilities cu;
+ private boolean unknownCodeSystemsCauseErrors;
public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) {
super(theContext, xverManager, false);
@@ -1125,7 +1126,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
if (s == null)
return true;
- ok = processTxIssues(errors, s, element, path, null, "no binding on code", false, null) & ok;
+ ok = processTxIssues(errors, s, element, path, false, null, null) & ok;
if (s.isOk()) {
if (s.getMessage() != null && !s.messageIsInIssues()) {
@@ -1381,7 +1382,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (cc.hasCoding()) {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, null, cc);
- bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, null, false, null));
+ bh.see(processTxIssues(errors, vr, element, path, false, null, null));
timeTracker.tx(t, "vc " + cc.toString());
}
} catch (CheckCodeOnServerException e) {
@@ -1465,7 +1466,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else {
checked.set(true);
ValidationResult vr = checkCodeOnServer(stack, valueset, cc);
- bh.see(processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef));
+ bh.see(processTxIssues(errors, vr, element, path, false, vsRef, strength));
if (!vr.isOk()) {
bindingsOk = false;
if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
@@ -1533,33 +1534,34 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return checkDisp;
}
- private String notFoundSeverityNoteForBinding(BindingStrength strength) {
- if (strength == BindingStrength.REQUIRED) {
- return "error because this is a required binding";
- } else {
- return null;
- }
- }
+// private String notFoundSeverityNoteForBinding(BindingStrength strength, Set systems) {
+// if (strength == BindingStrength.REQUIRED &&
+// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) {
+// return "error because this is a required binding to an HL7 code system";
+// } else {
+// return null;
+// }
+// }
+//
+// /**
+// * The terminology server will report an error for an unknown code system or version, or a dependent valueset
+// *
+// * but we only care for validation if the binding strength is strong enough.
+// * @param binding
+// * @return
+// */
+// private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength, String systems) {
+// if (strength == BindingStrength.REQUIRED &&
+// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) {
+// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
+// } else if (strength == BindingStrength.REQUIRED || strength == BindingStrength.EXTENSIBLE) {
+// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
+// } else {
+// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION;
+// }
+// }
- /**
- * The terminology server will report an error for an unknown code system or version, or a dependent valueset
- *
- * but we only care for validation if the binding strength is strong enough.
- * @param binding
- * @return
- */
- private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength) {
- if (strength == BindingStrength.REQUIRED) {
- return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
- } else if (strength == BindingStrength.EXTENSIBLE) {
- return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
- } else {
- return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION;
- }
- }
-
- private boolean processTxIssues(List errors, ValidationResult vr, Element element, String path,
- org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel, String notFoundNote, boolean ignoreCantInfer, String vsurl) {
+ private boolean processTxIssues(List errors, ValidationResult vr, Element element, String path, boolean ignoreCantInfer, String vsurl, BindingStrength bs) {
boolean ok = true;
if (vr != null) {
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
@@ -1567,12 +1569,35 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
&& !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs")
&& !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) {
OperationOutcomeIssueComponent i = iss.copy();
- if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
- if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel) || (vsurl != null && i.getDetails().getText().contains(vsurl))) {
- i.setSeverity(notFoundLevel);
+ if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
+ String msg = iss.getDetails().getText();
+ boolean isHL7 = msg == null ? false : msg.contains("http://hl7.org/fhir") || msg.contains("http://terminology.hl7.org");
+ org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel = null;
+ String notFoundNote = null;
+ if (bs == null) {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
+ notFoundNote = null; // "binding=null";
+ } else if (bs == BindingStrength.REQUIRED && isHL7) {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
+ notFoundNote = "error because this is a required binding to an HL7 code system";
+ } else if (bs == BindingStrength.REQUIRED && unknownCodeSystemsCauseErrors) {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
+ notFoundNote = "error because this is a required binding";
+ } else if (bs == BindingStrength.REQUIRED) {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
+ notFoundNote = null; // "binding=required";
+ } else if (bs == BindingStrength.EXTENSIBLE) {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
+ notFoundNote = null; // "binding=extensible";
+ } else {
+ notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
+ notFoundNote = null; // "binding="+bs.toCode();
}
- if (notFoundNote != null) {
- i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")");
+ if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel)) { // && (vsurl != null && i.getDetails().getText().contains(vsurl))) {
+ i.setSeverity(notFoundLevel);
+ if (notFoundNote != null) {
+ i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")");
+ }
}
}
if (baseOptions.isDisplayWarningMode() && i.getSeverity() == org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "invalid-display")) {
@@ -1592,7 +1617,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
boolean ok = true;
if (isNotBlank(nextCoding.getCode()) && isNotBlank(nextCoding.getSystem()) && context.supportsSystem(nextCoding.getSystem(), baseOptions.getFhirVersion())) {
ValidationResult vr = checkCodeOnServer(stack, valueset, nextCoding);
- ok = processTxIssues(errors, vr, element, path, null, "ex-checkBindings", false, null) && ok;
+ ok = processTxIssues(errors, vr, element, path, false, null, null) && ok;
if (vr.getSeverity() != null && !vr.messageIsInIssues()) {
if (vr.getSeverity() == IssueSeverity.INFORMATION) {
@@ -1721,7 +1746,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (strength == BindingStrength.REQUIRED) {
removeTrackedMessagesForLocation(errors, element, path);
}
- ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef) && ok;
+ ok = processTxIssues(errors, vr, element, path, false, vsRef, strength) && ok;
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
if (vr != null && !vr.isOk()) {
if (vr.IsNoService())
@@ -1766,6 +1791,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return ok;
}
+ private Set getUnknownSystems(ValidationResult vr) {
+ if (vr == null) {
+ return null;
+ }
+ if (vr.getUnknownSystems() != null && !vr.getUnknownSystems().isEmpty()) {
+ return vr.getUnknownSystems();
+ }
+ if (vr.getSystem() != null) {
+ Set set = new HashSet();
+ set.add(vr.getSystem());
+ return set;
+ }
+ return null;
+ }
+
private boolean convertCDACodeToCodeableConcept(List errors, String path, Element element, StructureDefinition logical, CodeableConcept cc) {
boolean ok = true;
cc.setText(element.getNamedChildValue("originalText", false));
@@ -1851,7 +1891,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, cc);
- ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet", false, maxVSUrl) && ok;
+ ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+cc.toString());
if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
@@ -1890,7 +1930,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, c);
- ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-2", false, maxVSUrl) && ok;
+ ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (!vr.isOk()) {
@@ -1921,7 +1961,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, value, baseOptions);
- ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-3", false, maxVSUrl) && ok;
+ ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+value);
if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
@@ -2045,7 +2085,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checked.set(true);
vr = checkCodeOnServer(stack, valueset, c);
}
- ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), strength == BindingStrength.EXTENSIBLE, vsRef) && ok;
+ ok = processTxIssues(errors, vr, element, path, strength == BindingStrength.EXTENSIBLE, vsRef, strength) && ok;
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (strength == BindingStrength.REQUIRED) {
@@ -3510,7 +3550,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
vr = checkCodeOnServer(stack, vs, value, options);
}
- ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(binding.getStrength()), notFoundSeverityNoteForBinding(binding.getStrength()), binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet()) && ok;
+ ok = processTxIssues(errors, vr, element, path, binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet(), binding.getStrength()) && ok;
timeTracker.tx(t, "vc "+value+"");
if (binding.getStrength() == BindingStrength.REQUIRED) {
@@ -7791,4 +7831,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.fetcher = value;
return this;
}
+
+ public boolean isUnknownCodeSystemsCauseErrors() {
+ return unknownCodeSystemsCauseErrors;
+ }
+
+ public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) {
+ this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
+ }
+
+
}
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java
index c4437511c..55376a293 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java
@@ -61,7 +61,7 @@ public class FHIRPathExpressionFixer {
}
// con-3 in R4
if (expr.equals("clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.select($this='problem-list-item').empty()")) {
- return "clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()";
+ return "(verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() and category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()) implies (clinicalStatus.exists())";
}
// R5 ballot
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java
index 35d069e8a..a85c4db8b 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java
@@ -8,10 +8,10 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import org.hl7.fhir.ParametersParameter;
+
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
-import org.hl7.fhir.r5.model.Base;
+
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java
index bd27a6f41..320f1dd30 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java
@@ -247,9 +247,9 @@ public class ValidationEngineTests {
Assertions.assertTrue(checkOutcomes("testObs102", op,
"Observation.text.div null error/invalid: Wrong namespace on the XHTML ('null', should be 'http://www.w3.org/1999/xhtml')\n"+
"Observation.category null information/business-rule: Reference to experimental CodeSystem http://hl7.org/fhir/observation-category\n"+
- "Observation.code.coding[2].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+
- "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()"));
+ "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()\n"+
+ "Observation.code.coding[2].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated"));
verifyNoTerminologyRequests(logger);
}
@@ -265,8 +265,8 @@ public class ValidationEngineTests {
System.out.println(" .. load USCore");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null);
Assertions.assertTrue(checkOutcomes("test301", op,
- "Observation.code.coding[3].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+
- "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer"));
+ "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+
+ "Observation.code.coding[3].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated"));
verifyNoTerminologyRequests(logger);
}
diff --git a/pom.xml b/pom.xml
index 61877213b..8589dbbe6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,14 +14,14 @@
HAPI FHIR
-->
org.hl7.fhir.core
- 6.3.24-SNAPSHOT
+ 6.3.26-SNAPSHOT
pom
1.26.0
32.0.1-jre
6.4.1
- 1.5.21-SNAPSHOT
+ 1.5.22-SNAPSHOT
2.17.0
5.9.2
1.8.2