list) {
+ for (String s : list) {
+ append(s);
+ }
+
+ }
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/MimeType.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/MimeType.java
index e3309e12c..d3a3f0b8d 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/MimeType.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/MimeType.java
@@ -90,4 +90,49 @@ public class MimeType {
return source;
}
+ public static String getExtension(String mimeType) {
+ MimeType mt = new MimeType(mimeType);
+ return mt.getExtension();
+ }
+
+ public String getExtension() {
+ switch (base) {
+ case "text/html" : return "html";
+ case "text/xml" : return "xml";
+ case "application/xml" : return "xml";
+ case "text/markdown" : return "md";
+ case "application/js" : return "js";
+ case "application/css" : return "css";
+ case "text/x-csrc" : return "c";
+ case "text/x-csharp" : return "cs";
+ case "text/x-c++src" : return "c";
+ case "application/graphql" : return "graphql";
+ case "application/x-java" : return "java";
+ case "application/json" : return "json";
+ case "text/json" : return "json";
+ case "application/liquid" : return "liquid";
+ case "text/x-pascal" : return "pas";
+ case "text/x-python" : return "py";
+ case "text/x-rsrc" : return "r";
+ case "text/x-ruby" : return "ruby";
+ case "text/x-sas" : return "sas";
+ case "text/x-sql" : return "sql";
+ case "application/typescript" : return "ts";
+ case "text/cql": return "cql";
+ case "image/png": return "png";
+ case "image/gif": return "gif";
+ case "image/jpeg": return "jpg";
+ }
+ if (base.contains("xml+") || base.contains("+xml")) {
+ return "xml";
+ }
+ if (base.contains("json+") || base.contains("+json")) {
+ return "json";
+ }
+ if (base.contains("turtle+") || base.contains("+turtle")) {
+ return "ttl";
+ }
+ return null;
+ }
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java
new file mode 100644
index 000000000..93c15dacb
--- /dev/null
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java
@@ -0,0 +1,46 @@
+package org.hl7.fhir.utilities;
+
+public class SourceLocation {
+ private int line;
+ private int column;
+ public SourceLocation(int line, int column) {
+ super();
+ this.line = line;
+ this.column = column;
+ }
+ public int getLine() {
+ return line;
+ }
+ public int getColumn() {
+ return column;
+ }
+ public void setLine(int line) {
+ this.line = line;
+ }
+ public void setColumn(int column) {
+ this.column = column;
+ }
+
+ public String toString() {
+ return Integer.toString(line)+", "+Integer.toString(column);
+ }
+
+ public void newLine() {
+ setLine(getLine() + 1);
+ setColumn(1);
+ }
+ public boolean checkChar(char ch, boolean last13) {
+ if (ch == '\r') {
+ newLine();
+ return true;
+ } else if (ch == '\n') {
+ if (!last13) {
+ newLine();
+ }
+ return false;
+ } else {
+ setColumn(getColumn() + 1);
+ return false;
+ }
+ }
+}
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java
index 2015c3e22..82d06017a 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java
@@ -47,6 +47,8 @@ import java.math.RoundingMode;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
@@ -320,13 +322,13 @@ public class Utilities {
destFile.createNewFile();
}
- FileChannel source = null;
- FileChannel destination = null;
+ FileInputStream source = null;
+ FileOutputStream destination = null;
try {
- source = new FileInputStream(sourceFile).getChannel();
- destination = new FileOutputStream(destFile).getChannel();
- destination.transferFrom(source, 0, source.size());
+ source = new FileInputStream(sourceFile);
+ destination = new FileOutputStream(destFile);
+ destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size());
} finally {
if (source != null) {
source.close();
@@ -398,8 +400,8 @@ public class Utilities {
clearDirectory(fh.getAbsolutePath());
fh.delete();
}
+ }
}
- }
}
}
}
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java
index 3b303a035..c74687d8b 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.exceptions.FHIRException;
-import org.hl7.fhir.utilities.cache.NpmPackage;
+import org.hl7.fhir.utilities.npm.NpmPackage;
/*
Copyright (c) 2011+, HL7, Inc.
@@ -181,6 +181,10 @@ public class VersionUtilities {
public static String getMajMin(String version) {
if (version == null)
return null;
+
+ if ("current".equals(version)) {
+ return CURRENT_VERSION;
+ }
if (Utilities.charCount(version, '.') == 1) {
String[] p = version.split("\\.");
@@ -193,6 +197,16 @@ public class VersionUtilities {
}
}
+ public static String getPatch(String version) {
+ if (version == null)
+ return null;
+ if (Utilities.charCount(version, '.') == 2) {
+ String[] p = version.split("\\.");
+ return p[2];
+ }
+ return null;
+ }
+
public static boolean isSemVer(String version) {
if (Utilities.charCount(version, '.') != 2) {
return false;
@@ -202,7 +216,7 @@ public class VersionUtilities {
}
/**
- * return true if the current vresion equals test, or later
+ * return true if the current version equals test, or later
*
* so if a feature is defined in 4.0, if (VersionUtilities.isThisOrLater("4.0", version))...
*
@@ -213,10 +227,36 @@ public class VersionUtilities {
public static boolean isThisOrLater(String test, String current) {
String t = getMajMin(test);
String c = getMajMin(current);
+ if (c.compareTo(t) == 0) {
+ return isMajMinOrLaterPatch(test, current);
+ }
boolean ok = c.compareTo(t) >= 0;
return ok;
}
+ /**
+ * return true if the current version equals test for major and min, or later patch
+ *
+ * @param test
+ * @param current
+ * @return
+ */
+ public static boolean isMajMinOrLaterPatch(String test, String current) {
+ String t = getMajMin(test);
+ String c = getMajMin(current);
+ if (c != null && c.compareTo(t) == 0) {
+ String pt = getPatch(test);
+ String pc = getPatch(current);
+ if (pt==null || "x".equals(pt)) {
+ return true;
+ }
+ if (pc!=null) {
+ return pc.compareTo(pt) >= 0;
+ }
+ }
+ return false;
+ }
+
public static String incMajorVersion(String v) {
assert isSemVer(v);
int[] parts = splitParts(v);
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java
index 1d5359d76..4d9da697d 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java
@@ -341,6 +341,8 @@ public class I18nConstants {
public static final String RESOURCE_TYPE_MISMATCH_FOR___ = "Resource_type_mismatch_for___";
public static final String SAME_ID_ON_MULTIPLE_ELEMENTS__IN_ = "Same_id_on_multiple_elements__in_";
public static final String SD_MUST_HAVE_DERIVATION = "SD_MUST_HAVE_DERIVATION";
+ public static final String SD_NESTED_MUST_SUPPORT_DIFF = "SD_NESTED_MUST_SUPPORT_DIFF";
+ public static final String SD_NESTED_MUST_SUPPORT_SNAPSHOT = "SD_NESTED_MUST_SUPPORT_SNAPSHOT";
public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG";
public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG";
public static final String SEARCHPARAMETER_NOTFOUND = "SEARCHPARAMETER_NOTFOUND";
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java
index e133d2f02..977d6873b 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java
@@ -36,6 +36,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
+import java.net.HttpURLConnection;
+import java.net.URL;
import java.util.Map;
import java.util.Stack;
@@ -671,6 +673,13 @@ public class JsonTrackingParser {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(json);
}
+
+ public static JsonObject fetchJson(String source) throws IOException {
+ URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
+ HttpURLConnection c = (HttpURLConnection) url.openConnection();
+ c.setInstanceFollowRedirects(true);
+ return parseJson(c.getInputStream());
+ }
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java
similarity index 97%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java
index 82e295e89..c116eb058 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.exceptions.FHIRException;
@@ -69,6 +69,9 @@ public abstract class BasePackageCacheManager implements IPackageCacheManager {
if (Utilities.noString(version)) {
version = packageClient.getLatestVersion(id);
}
+ if (version.endsWith(".x")) {
+ version = packageClient.getLatestVersion(id, version);
+ }
InputStream stream = packageClient.fetch(id, version);
String url = packageClient.url(id, version);
return new InputStreamWithSrc(stream, url, version);
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/CachingPackageClient.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/CachingPackageClient.java
similarity index 97%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/CachingPackageClient.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/CachingPackageClient.java
index 571dd59c9..e5812be8f 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/CachingPackageClient.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/CachingPackageClient.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import java.io.File;
import java.io.FileInputStream;
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java
similarity index 95%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java
index bf9bdac65..985065479 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
/*
Copyright (c) 2011+, HL7, Inc.
@@ -39,8 +39,9 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
-import org.hl7.fhir.utilities.cache.NpmPackage.NpmPackageFolder;
+import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.json.JSONUtil;
+import org.hl7.fhir.utilities.npm.NpmPackage.NpmPackageFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -283,7 +284,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
}
/**
- * Load the identified package from the cache - it it exists
+ * Load the identified package from the cache - if it exists
*
* This is for special purpose only (testing, control over speed of loading).
* Generally, use the loadPackage method
@@ -307,11 +308,26 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
return p;
}
}
+ String foundPackage = null;
+ String foundVersion = null;
for (String f : sorted(new File(cacheFolder).list())) {
- if (f.equals(id + "#" + version) || (Utilities.noString(version) && f.startsWith(id + "#"))) {
- return loadPackageInfo(Utilities.path(cacheFolder, f));
+ File cf = new File(Utilities.path(cacheFolder, f));
+ if (cf.isDirectory()) {
+ if (f.equals(id + "#" + version) || (Utilities.noString(version) && f.startsWith(id + "#"))) {
+ return loadPackageInfo(Utilities.path(cacheFolder, f));
+ }
+ if (version != null && version.endsWith(".x") && f.contains("#")) {
+ String[] parts = f.split("#");
+ if (parts[0].equals(id) && VersionUtilities.isMajMinOrLaterPatch((foundVersion!=null ? foundVersion : version),parts[1])) {
+ foundVersion = parts[1];
+ foundPackage = f;
+ }
+ }
}
}
+ if (foundPackage!=null) {
+ return loadPackageInfo(Utilities.path(cacheFolder, foundPackage));
+ }
if ("dev".equals(version))
return loadPackageFromCacheOnly(id, "current");
else
@@ -895,33 +911,4 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
return false;
}
-
-
-
-//public List getUrls() throws IOException {
-// if (allUrls == null)
-// {
-// IniFile ini = new IniFile(Utilities.path(cacheFolder, "packages.ini"));
-// allUrls = new ArrayList<>();
-// for (String s : ini.getPropertyNames("urls"))
-// allUrls.add(ini.getStringProperty("urls", s));
-// try {
-// URL url = new URL("https://raw.githubusercontent.com/FHIR/ig-registry/master/fhir-ig-list.json?nocache=" + System.currentTimeMillis());
-// HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-// connection.setRequestMethod("GET");
-// InputStream json = connection.getInputStream();
-// JsonObject packages = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.streamToString(json));
-// JsonArray guides = packages.getAsJsonArray("guides");
-// for (JsonElement g : guides) {
-// JsonObject gi = (JsonObject) g;
-// if (gi.has("canonical"))
-// if (!allUrls.contains(gi.get("canonical").getAsString()))
-// allUrls.add(gi.get("canonical").getAsString());
-// }
-// } catch (Exception e) {
-// System.out.println("Listing known Implementation Guides failed: "+e.getMessage());
-// }
-// }
-// return allUrls;
-//}
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/IPackageCacheManager.java
similarity index 94%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/IPackageCacheManager.java
index eaeeebc48..99e19e511 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/IPackageCacheManager.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import org.hl7.fhir.exceptions.FHIRException;
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java
similarity index 99%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java
index b87b60818..5f1415f62 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
/*
Copyright (c) 2011+, HL7, Inc.
@@ -61,10 +61,10 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
-import org.hl7.fhir.utilities.cache.NpmPackage.PackageResourceInformationSorter;
-import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
+import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformationSorter;
+import org.hl7.fhir.utilities.npm.PackageGenerator.PackageType;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
@@ -814,7 +814,7 @@ public class NpmPackage {
public String getWebLocation() {
if (npm.has("url")) {
- return npm.get("url").getAsString();
+ return PackageHacker.fixPackageUrl(npm.get("url").getAsString());
} else {
return JSONUtil.str(npm, "canonical");
}
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java
similarity index 97%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java
index 5ae42d265..8d14a449b 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import java.io.File;
import java.io.IOException;
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java
similarity index 73%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java
index ac1457b08..3fdaa7e35 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -8,6 +8,7 @@ import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.json.JSONUtil;
+import org.hl7.fhir.utilities.json.JsonTrackingParser;
import java.io.File;
import java.io.FileInputStream;
@@ -208,5 +209,61 @@ public class PackageClient {
}
}
+ public String getLatestVersion(String id, String majMinVersion) throws IOException {
+ List list = getVersions(id);
+ if (list.isEmpty()) {
+ throw new IOException("Package not found: "+id);
+ } else {
+ String v = majMinVersion;
+ for (PackageInfo p : list) {
+ if (VersionUtilities.isMajMinOrLaterPatch(v, p.version)) {
+ v = p.version;
+ }
+ }
+ return v;
+ }
+ }
+
+ public List listFromRegistry(String name, String canonical, String fhirVersion) throws IOException {
+ List result = new ArrayList<>();
+ JsonObject packages = JsonTrackingParser.fetchJson("https://raw.githubusercontent.com/FHIR/ig-registry/master/fhir-ig-list.json?nocache=" + System.currentTimeMillis());
+ for (JsonObject o : JSONUtil.objects(packages, "guides")) {
+ if (o.has("canonical")) {
+ String id = JSONUtil.str(o, "npm-name");
+ String pname = JSONUtil.str(o, "name");
+ String pcanonical = JSONUtil.str(o, "canonical");
+ String description = JSONUtil.str(o, "description");
+ boolean ok = true;
+ if (ok && !Utilities.noString(name)) {
+ ok = (pname != null && pname.contains(name)) || (description != null && description.contains(name)) || (id != null && id.contains(name));
+ }
+ if (ok && !Utilities.noString(canonical)) {
+ ok = pcanonical.contains(canonical);
+ }
+ String version = null;
+ String fVersion = null;
+ String url = null;
+
+ if (ok) {
+ // if we can find something...
+ for (JsonObject e : JSONUtil.objects(o, "editions")) {
+ if (fhirVersion == null || fhirVersion.equals(JSONUtil.str(e, "fhir-version"))) {
+ String v = JSONUtil.str(e, "ig-version");
+ if (version == null || VersionUtilities.isThisOrLater(version, v)) {
+ version = v;
+ fVersion = e.getAsJsonArray("fhir-version").get(0).getAsString();
+ url = JSONUtil.str(e, "url");
+ }
+ }
+ }
+ }
+ if (version != null) {
+ result.add(new PackageInfo(id, version, fVersion, description, url, pcanonical));
+ }
+ }
+ }
+ return result;
+ }
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageGenerator.java
similarity index 99%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageGenerator.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageGenerator.java
index a39e537a7..d4d73c1a0 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageGenerator.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageGenerator.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
/*
Copyright (c) 2011+, HL7, Inc.
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
similarity index 92%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageHacker.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
index ba3319bbe..26e7d9637 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageHacker.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
import java.io.File;
import java.io.FileInputStream;
@@ -25,7 +25,7 @@ import com.google.gson.JsonObject;
public class PackageHacker {
public static void main(String[] args) throws FileNotFoundException, IOException {
- new PackageHacker().edit("M:\\web\\hl7.org\\fhir\\uv\\cdisc-lab\\package.tgz");
+ new PackageHacker().edit("M:\\web\\hl7.org\\fhir\\us\\carin-rtpbc\\package.tgz");
}
private void edit(String name) throws FileNotFoundException, IOException {
@@ -58,9 +58,9 @@ public class PackageHacker {
private void change(JsonObject npm, Map content) throws FileNotFoundException, IOException {
fixVersions(npm);
npm.remove("url");
- npm.addProperty("url", "http://hl7.org/fhir/uv/cdisc-lab/STU1");
- npm.remove("name");
- npm.addProperty("name", "hl7.fhir.uv.cdisc-lab");
+ npm.addProperty("url", "http://hl7.org/fhir/us/carin-rtpbc/STU1");
+// npm.remove("name");
+// npm.addProperty("name", "hl7.fhir.uv.smart-app-launch");
// npm.remove("canonical");
// npm.addProperty("canonical", "http://hl7.org/fhir/us/davinci-drug-formulary");
//// npm.remove("description");
@@ -70,7 +70,7 @@ public class PackageHacker {
// npm.remove("dependencies");
// JsonObject dep = new JsonObject();
// npm.add("dependencies", dep);
-// dep.addProperty("hl7.fhir.r4.core", "4.0.1");
+// dep.addProperty("hl7.fhir.r3.core", "3.0.1");
// dep.addProperty("hl7.fhir.r4.examples", "4.0.1");
// dep.addProperty("hl7.fhir.r4.expansions", "4.0.1");
// dep.addProperty("hl7.fhir.r4.elements", "4.0.1");
@@ -80,7 +80,7 @@ public class PackageHacker {
npm.remove("fhirVersions");
JsonArray a = new JsonArray();
npm.add("fhirVersions", a);
- a.add("4.5.0");
+ a.add("3.0.1");
}
private void setProperty(JsonObject npm, String name, String value) {
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/ToolsVersion.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/ToolsVersion.java
similarity index 97%
rename from org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/ToolsVersion.java
rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/ToolsVersion.java
index 7ece6c31e..018ad9c12 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/ToolsVersion.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/ToolsVersion.java
@@ -1,4 +1,4 @@
-package org.hl7.fhir.utilities.cache;
+package org.hl7.fhir.utilities.npm;
/*
Copyright (c) 2011+, HL7, Inc.
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/turtle/Turtle.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/turtle/Turtle.java
index a92f03c66..a555698a3 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/turtle/Turtle.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/turtle/Turtle.java
@@ -384,12 +384,12 @@ public class Turtle {
public String asHtml() throws Exception {
StringBuilder b = new StringBuilder();
- b.append("\r\n");
+ b.append("\r\n");
commitPrefixes(b);
for (Section s : sections) {
commitSection(b, s);
}
- b.append("
\r\n");
+ b.append("
\r\n");
b.append("\r\n");
return b.toString();
}
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java
index d501ff789..e561009f2 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java
@@ -38,9 +38,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
+import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
+import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.Utilities;
+import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
@@ -86,6 +90,9 @@ public class XhtmlNode implements IBaseXhtml {
private List childNodes = new ArrayList();
private String content;
private boolean notPretty;
+ private boolean inPara;
+ private boolean inLink;
+
public XhtmlNode() {
super();
@@ -140,7 +147,7 @@ public class XhtmlNode implements IBaseXhtml {
return this;
}
- public void validate(List errors, String path, boolean inResource, boolean inPara) {
+ public void validate(List errors, String path, boolean inResource, boolean inPara, boolean inLink) {
if (nodeType == NodeType.Element || nodeType == NodeType.Document) {
path = Utilities.noString(path) ? name : path+"/"+name;
if (inResource) {
@@ -168,13 +175,19 @@ public class XhtmlNode implements IBaseXhtml {
if (inPara && Utilities.existsInList(name, "div", "blockquote", "table", "ol", "ul", "p")) {
errors.add("Error at "+path+": Found "+name+" inside an html paragraph");
}
+ if (inLink && Utilities.existsInList(name, "a")) {
+ errors.add("Error at "+path+": Found an inside an paragraph");
+ }
if (childNodes != null) {
if ("p".equals(name)) {
inPara = true;
}
+ if ("a".equals(name)) {
+ inLink = true;
+ }
for (XhtmlNode child : childNodes) {
- child.validate(errors, path, inResource, inPara);
+ child.validate(errors, path, inResource, inPara, inLink);
}
}
}
@@ -187,8 +200,20 @@ public class XhtmlNode implements IBaseXhtml {
throw new Error("Wrong node type - node is "+nodeType.toString()+" ('"+getName()+"/"+getContent()+"')");
}
+// if (inPara && name.equals("p")) {
+// throw new FHIRException("nested Para");
+// }
+// if (inLink && name.equals("a")) {
+// throw new FHIRException("Nested Link");
+// }
XhtmlNode node = new XhtmlNode(NodeType.Element);
node.setName(name);
+ if (inPara || name.equals("p")) {
+ node.inPara = true;
+ }
+ if (inLink || name.equals("a")) {
+ node.inLink = true;
+ }
childNodes.add(node);
return node;
}
@@ -199,6 +224,12 @@ public class XhtmlNode implements IBaseXhtml {
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document))
throw new Error("Wrong node type. is "+nodeType.toString());
XhtmlNode node = new XhtmlNode(NodeType.Element);
+ if (inPara || name.equals("p")) {
+ node.inPara = true;
+ }
+ if (inLink || name.equals("a")) {
+ node.inLink = true;
+ }
node.setName(name);
childNodes.add(index, node);
return node;
@@ -796,6 +827,21 @@ public class XhtmlNode implements IBaseXhtml {
}
+ public void markdown(String md, String source) throws IOException {
+ if (md != null) {
+ String s = new MarkDownProcessor(Dialect.COMMON_MARK).process(md, source);
+ XhtmlParser p = new XhtmlParser();
+ XhtmlNode m;
+ try {
+ m = p.parse(""+s+"
", "div");
+ } catch (org.hl7.fhir.exceptions.FHIRFormatError e) {
+ throw new FHIRFormatError(e.getMessage(), e);
+ }
+ getChildNodes().addAll(m.getChildNodes());
+ }
+ }
+
+
diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties
index 8a13d0256..f9d145fbf 100644
--- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties
+++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties
@@ -10,8 +10,8 @@ Bundle_BUNDLE_Entry_NoFullUrl = Bundle entry missing fullUrl
Bundle_BUNDLE_Entry_NoProfile = No profile found for contained resource of type ''{0}''
Bundle_BUNDLE_Entry_NotFound = Can''t find ''{0}'' in the bundle ({1})
Bundle_BUNDLE_Entry_Orphan = Entry {0} isn''t reachable by traversing from first Bundle entry
-Bundle_BUNDLE_Entry_Type = The type ''{0}'' is not valid - no resources allowed here
-Bundle_BUNDLE_Entry_Type2 = The type ''{0}'' is not valid - must be {1}
+Bundle_BUNDLE_Entry_Type = The type ''{0}'' is not valid - no resources allowed here (allowed = {1})
+Bundle_BUNDLE_Entry_Type2 = The type ''{0}'' is not valid - must be {1} (allowed = {2})
Bundle_BUNDLE_Entry_Type3 = The type ''{0}'' is not valid - must be one of {1}
Bundle_BUNDLE_FullUrl_Missing = Relative Reference appears inside Bundle whose entry is missing a fullUrl
Bundle_BUNDLE_FullUrl_NeedVersion = Entries matching fullURL {0} should declare meta/versionId because there are version-specific references
@@ -133,11 +133,11 @@ Terminology_TX_Code_ValueSetMax = No code provided, and a code must be provided
Terminology_TX_Code_ValueSet_Ext = No code provided, and a code should be provided from the value set {0} ({1})
Terminology_TX_Coding_Count = Expected {0} but found {1} coding elements
Terminology_TX_Confirm_1 = Could not confirm that the codes provided are in the value set {0} and a code from this value set is required (class = {1})
-Terminology_TX_Confirm_2 = Could not confirm that the codes provided are in the value set {0} and a code should come from this value set unless it has no suitable code (class = {1})
+Terminology_TX_Confirm_2 = Could not confirm that the codes provided are in the value set {0} and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) (class = {1})
Terminology_TX_Confirm_3 = Could not confirm that the codes provided are in the value set {0} and a code is recommended to come from this value set (class = {1})
Terminology_TX_Confirm_4a = The code provided ({2}) is not in the value set {0}, and a code from this value set is required: {1}
Terminology_TX_Confirm_4b = The codes provided ({2}) are not in the value set {0}, and a code from this value set is required: {1}
-Terminology_TX_Confirm_5 = Could not confirm that the codes provided are in the value set {0}, and a code should come from this value set unless it has no suitable code
+Terminology_TX_Confirm_5 = Could not confirm that the codes provided are in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable)
Terminology_TX_Confirm_6 = Could not confirm that the codes provided are in the value set {0}, and a code is recommended to come from this value set
Terminology_TX_Display_Wrong = Display should be ''{0}''
Terminology_TX_Error_CodeableConcept = Error {0} validating CodeableConcept
@@ -148,17 +148,17 @@ Terminology_TX_NoValid_1 = None of the codes provided are in the value set {0} (
Terminology_TX_NoValid_10 = The code provided is not in the maximum value set {0} ({1}), and a code from this value set is required) (code = {2}#{3})
Terminology_TX_NoValid_11 = The code provided is not in the maximum value set {0} ({1}{2})
Terminology_TX_NoValid_12 = The Coding provided ({2}) is not in the value set {0}, and a code is required from this value set. {1}
-Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code. {1}
+Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable). {1}
Terminology_TX_NoValid_14 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set. {1}
Terminology_TX_NoValid_15 = The value provided (''{0}'') could not be validated in the absence of a terminology server
Terminology_TX_NoValid_16 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code is required from this value set){3}
-Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code should come from this value set unless it has no suitable code){3}
+Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code should come from this value set unless it has no suitable code and the validator cannot judge what is suitable){3}
Terminology_TX_NoValid_18 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code is recommended to come from this value set){3}
-Terminology_TX_NoValid_2 = None of the codes provided are in the value set {0} ({1}), and a code should come from this value set unless it has no suitable code) (codes = {2})
+Terminology_TX_NoValid_2 = None of the codes provided are in the value set {0} ({1}), and a code should come from this value set unless it has no suitable code and the validator cannot judge what is suitable) (codes = {2})
Terminology_TX_NoValid_3 = None of the codes provided are in the value set {0} ({1}), and a code is recommended to come from this value set) (codes = {2})
-Terminology_TX_NoValid_4 = The Coding provided ({2}) is not in the value set {0}, and a code is required from this value set{1}
-Terminology_TX_NoValid_5 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code{1}
-Terminology_TX_NoValid_6 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set{1}
+Terminology_TX_NoValid_4 = The Coding provided ({2}) is not in the value set {0}, and a code is required from this value set {1}
+Terminology_TX_NoValid_5 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) {1}
+Terminology_TX_NoValid_6 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set {1}
Terminology_TX_NoValid_7 = None of the codes provided could be validated against the maximum value set {0} ({1}), (error = {2})
Terminology_TX_NoValid_8 = None of the codes provided are in the maximum value set {0} ({1}), and a code from this value set is required) (codes = {2})
Terminology_TX_NoValid_9 = The code provided could not be validated against the maximum value set {0} ({1}), (error = {2})
@@ -608,4 +608,7 @@ REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect,
TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable
XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'')
UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported property {3} on type {2} for pattern for discriminator({0}) for slice {1}
-UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator({0}) for slice {1}
\ No newline at end of file
+UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator({0}) for slice {1}
+SD_NESTED_MUST_SUPPORT_DIFF = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support. The inner must-supports will be ignored unless the element inherits must-support = true
+SD_NESTED_MUST_SUPPORT_SNAPSHOT = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support
+
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/CachingPackageClientTests.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/CachingPackageClientTests.java
index 2e897e910..3ba3e61e3 100644
--- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/CachingPackageClientTests.java
+++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/CachingPackageClientTests.java
@@ -1,7 +1,7 @@
package org.hl7.fhir.utilities.tests;
-import org.hl7.fhir.utilities.cache.CachingPackageClient;
-import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
+import org.hl7.fhir.utilities.npm.CachingPackageClient;
+import org.hl7.fhir.utilities.npm.PackageClient.PackageInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -104,4 +104,12 @@ public class CachingPackageClientTests {
List matches = client.getVersions("Simplifier.Core.STU3X");
Assertions.assertTrue(matches.size() == 0);
}
+
+ @Test
+ public void testRegistry() throws IOException {
+ CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org/packages");
+ List matches1 = client.listFromRegistry(null, null, null);
+ List matches2 = client.listFromRegistry(null, null, "4.0.1");
+ Assertions.assertTrue(matches1.size() > matches2.size());
+ }
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/PackageCacheTests.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/PackageCacheTests.java
index 4f42035eb..05d38d4d8 100644
--- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/PackageCacheTests.java
+++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/PackageCacheTests.java
@@ -1,9 +1,9 @@
package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.utilities.Utilities;
-import org.hl7.fhir.utilities.cache.NpmPackage;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.NpmPackage;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -37,4 +37,14 @@ public class PackageCacheTests {
list = cache.listPackages();
Assertions.assertFalse(list.isEmpty());
}
+
+ @Test
+ public void testPatchWildCard() throws IOException {
+ FilesystemPackageCacheManager cache = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
+ cache.clear();
+ Assertions.assertEquals(cache.loadPackage("hl7.fhir.us.core", "3.1.0").version(), "3.1.0");
+ Assertions.assertEquals(cache.loadPackage("hl7.fhir.us.core", "3.1.1").version(), "3.1.1");
+ Assertions.assertEquals(cache.loadPackage("hl7.fhir.us.core", "3.1.x").version(), "3.1.1");
+ Assertions.assertEquals(cache.loadPackage("hl7.fhir.us.core", "3.0.x").version(), "3.0.1");
+ }
}
\ No newline at end of file
diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml
index 07c20fc2f..a8dcf2676 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
- 5.1.11-SNAPSHOT
+ 5.1.17-SNAPSHOT
../pom.xml
diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml
index db2bc5c32..ffa5971b1 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
- 5.1.11-SNAPSHOT
+ 5.1.17-SNAPSHOT
../pom.xml
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java
index 9e1bd5dd3..8e7b585a7 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java
@@ -296,9 +296,10 @@ public class BaseValidator {
* Set this parameter to false
if the validation does not pass
* @return Returns thePass
(in other words, returns true
if the rule did not fail validation)
*/
- protected boolean hint(List errors, IssueType type, String path, boolean thePass, String msg) {
+ protected boolean hint(List errors, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
- addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null);
+ String message = context.formatMessage(theMessage, theMessageArguments);
+ addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, null);
}
return thePass;
}
@@ -528,6 +529,21 @@ public class BaseValidator {
return thePass;
}
+ /**
+ * Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
+ *
+ * @param thePass
+ * Set this parameter to false
if the validation does not pass
+ * @return Returns thePass
(in other words, returns true
if the rule did not fail validation)
+ */
+ protected boolean warningOrHint(List errors, IssueType type, String path, boolean thePass, boolean warning, String msg, Object... theMessageArguments) {
+ if (!thePass) {
+ String message = context.formatMessage(msg, theMessageArguments);
+ addValidationMessage(errors, type, -1, -1, path, message, warning ? IssueSeverity.WARNING : IssueSeverity.INFORMATION, null);
+ }
+ return thePass;
+ }
+
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
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 b6ca6b9f2..596055d66 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
@@ -34,7 +34,13 @@ import org.hl7.fhir.r5.utils.*;
import org.hl7.fhir.r5.utils.IResourceValidator.*;
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.i18n.I18nConstants;
+import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.NpmPackage;
+import org.hl7.fhir.utilities.npm.PackageClient;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.hl7.fhir.validation.BaseValidator.ValidationControl;
+import org.hl7.fhir.validation.Validator.QuestionnaireMode;
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
import org.hl7.fhir.validation.instance.InstanceValidator;
import org.hl7.fhir.utilities.IniFile;
@@ -42,11 +48,6 @@ import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
-import org.hl7.fhir.utilities.cache.NpmPackage;
-import org.hl7.fhir.utilities.cache.PackageClient;
-import org.hl7.fhir.utilities.cache.BasePackageCacheManager;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.i18n.I18nBase;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage;
@@ -311,6 +312,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
private boolean showTimes;
private List bundleValidationRules = new ArrayList<>();
private Map validationControl = new HashMap<>();
+ private QuestionnaireMode questionnaireMode;
private class AsteriskFilter implements FilenameFilter {
String dir;
@@ -531,7 +533,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
v = src.substring(src.indexOf("|")+1);
src = src.substring(0, src.indexOf("|"));
}
- String pid = pcm.getPackageId(src);
+ String pid = explore ? pcm.getPackageId(src) : null;
if (!Utilities.noString(pid))
return fetchByPackage(pid+(v == null ? "" : "#"+v));
else
@@ -563,7 +565,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
return fetchByPackage(src);
}
- throw new FHIRException("Unable to find/resolve/read -ig "+src);
+ throw new FHIRException("Unable to find/resolve/read "+(explore ? "-ig " : "")+src);
}
private Map loadIgSourceForVersion(String src, boolean recursive, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
@@ -642,18 +644,26 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
// ok, having tried all that... now we'll just try to access it directly
byte[] cnt;
- if (stream == null)
- cnt = fetchFromUrlSpecific(src, "application/json", true);
- else
+ List errors = new ArrayList<>();
+ if (stream != null) {
cnt = TextFile.streamToBytes(stream);
-
+ } else {
+ cnt = fetchFromUrlSpecific(src, "application/json", true, errors);
+ if (cnt == null) {
+ cnt = fetchFromUrlSpecific(src, "application/xml", true, errors);
+ }
+ }
+ if (cnt == null) {
+ throw new FHIRException("Unable to fetch content from "+src+" ("+errors.toString()+")");
+
+ }
FhirFormat fmt = checkIsResource(cnt, src);
if (fmt != null) {
Map res = new HashMap();
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
return res;
}
- throw new FHIRException("Unable to find/resolve/read -ig "+src);
+ throw new FHIRException("Unable to read content from "+src+": cannot determine format");
}
private Map fetchVersionFromUrl(String src, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
@@ -687,7 +697,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
// ok, having tried all that... now we'll just try to access it directly
byte[] cnt;
if (stream == null)
- cnt = fetchFromUrlSpecific(src, "application/json", true);
+ cnt = fetchFromUrlSpecific(src, "application/json", true, null);
else
cnt = TextFile.streamToBytes(stream);
@@ -697,7 +707,20 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
return res;
}
- throw new FHIRException("Unable to find/resolve/read -ig "+src);
+ String fn = Utilities.path("[tmp]", "fetch-resource-error-content.bin");
+ TextFile.bytesToFile(cnt, fn);
+ System.out.println("Error Fetching "+src);
+ System.out.println("Some content was found, saved to "+fn);
+ System.out.println("1st 100 bytes = "+presentForDebugging(cnt));
+ throw new FHIRException("Unable to find/resolve/read "+(explore ? "-ig " : "")+src);
+ }
+
+ private String presentForDebugging(byte[] cnt) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < Integer.min(cnt.length, 50); i++) {
+ b.append(Integer.toHexString(cnt[i]));
+ }
+ return b.toString();
}
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException, IOException {
@@ -713,13 +736,24 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
}
- private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional) throws FHIRException, IOException {
+ private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional, List errors) throws FHIRException, IOException {
try {
- URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestProperty("Accept", contentType);
- return TextFile.streamToBytes(conn.getInputStream());
+ try {
+ // try with cache-busting option and then try withhout in case the server doesn't support that
+ URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestProperty("Accept", contentType);
+ return TextFile.streamToBytes(conn.getInputStream());
+ } catch (Exception e) {
+ URL url = new URL(source);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestProperty("Accept", contentType);
+ return TextFile.streamToBytes(conn.getInputStream());
+ }
} catch (IOException e) {
+ if (errors != null) {
+ errors.add("Error accessing "+source+": "+e.getMessage());
+ }
if (optional)
return null;
else
@@ -762,6 +796,18 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
context.getLoadedPackages().add(pi.name()+"#"+pi.version());
Map res = new HashMap();
for (String s : pi.dependencies()) {
+ if (s.endsWith(".x") && s.length()>2) {
+ String packageMajorMinor = s.substring(0, s.length()-2);
+ boolean found = false;
+ for (int i=0; i questionnaires) {
+ public void setQuestionnaireMode(Validator.QuestionnaireMode questionnaireMode) {
+ this.questionnaireMode = questionnaireMode;
}
public void setNative(boolean doNative) {
@@ -1123,8 +1170,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
FhirFormat cntType = null;
}
- public Content loadContent(String source, String opName) throws FHIRException, IOException {
- Map s = loadIgSource(source, false, false);
+ public Content loadContent(String source, String opName, boolean asIg) throws FHIRException, IOException {
+ Map s = loadIgSource(source, false, asIg);
Content res = new Content();
if (s.size() != 1)
throw new FHIRException("Unable to find resource " + source + " to "+opName);
@@ -1180,7 +1227,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
InstanceValidator validator = getValidator();
for (String ref : refs) {
- Content cnt = loadContent(ref, "validate");
+ Content cnt = loadContent(ref, "validate", false);
List messages = new ArrayList();
Element e = null;
try {
@@ -1252,7 +1299,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
List refs = new ArrayList();
handleSources(sources, refs);
for (String ref : refs) {
- Content cnt = loadContent(ref, "validate");
+ Content cnt = loadContent(ref, "validate", false);
String s = TextFile.bytesToString(cnt.focus);
if (s.contains("http://hl7.org/fhir/3.0")) {
versions.see("3.0", "Profile in "+ref);
@@ -1281,7 +1328,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
TimeTracker.Session tts = context.clock().start("validation");
context.clock().milestone();
System.out.print(" Validate " + ref);
- Content cnt = loadContent(ref, "validate");
+ Content cnt = loadContent(ref, "validate", false);
try {
OperationOutcome outcome = validate(ref, cnt.focus, cnt.cntType, profiles);
ToolingExtensions.addStringExtension(outcome, ToolingExtensions.EXT_OO_FILE, ref);
@@ -1473,7 +1520,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
public org.hl7.fhir.r5.elementmodel.Element transform(String source, String map) throws FHIRException, IOException {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
return transform(cnt.focus, cnt.cntType, map);
}
@@ -1518,7 +1565,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
public DomainResource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
Resource res = loadResourceByVersion(version, cnt.focus, source);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RendererFactory.factory(res, rc).render((DomainResource) res);
@@ -1526,20 +1573,20 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
public void convert(String source, String output) throws FHIRException, IOException {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
Manager.compose(context, e, new FileOutputStream(output), (output.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML), OutputStyle.PRETTY, null);
}
public String evaluateFhirPath(String source, String expression) throws FHIRException, IOException {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
FHIRPathEngine fpe = new FHIRPathEngine(context);
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
return fpe.evaluateToString(e, expression);
}
public StructureDefinition snapshot(String source, String version) throws FHIRException, IOException {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
Resource res = loadResourceByVersion(version, cnt.focus, Utilities.getFileNameForName(source));
if (!(res instanceof StructureDefinition))
@@ -1583,11 +1630,14 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
validator.getImplementationGuides().addAll(igs);
validator.getBundleValidationRules().addAll(bundleValidationRules);
validator.getValidationControl().putAll(validationControl );
+ validator.setQuestionnaireMode(questionnaireMode);
return validator;
}
public void setMapLog(String mapLog) throws FileNotFoundException {
- this.mapLog = new PrintWriter(mapLog);
+ if (mapLog != null) {
+ this.mapLog = new PrintWriter(mapLog);
+ }
}
public void prepare() {
@@ -2042,7 +2092,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
public byte[] transformVersion(String source, String targetVer, FhirFormat format, Boolean canDoNative) throws FHIRException, IOException, Exception {
- Content cnt = loadContent(source, "validate");
+ Content cnt = loadContent(source, "validate", false);
org.hl7.fhir.r5.elementmodel.Element src = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
// if the src has a url, we try to use the java code
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java
index 8b6a38bf3..be1da42f0 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java
@@ -91,6 +91,8 @@ public class Validator {
public enum EngineMode {
VALIDATION, TRANSFORM, NARRATIVE, SNAPSHOT, SCAN, CONVERT, FHIRPATH, VERSION
}
+
+ public enum QuestionnaireMode { NONE, CHECK, REQUIRED }
private static CliContext cliContext;
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 1ed9893a9..eea13ac6c 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
@@ -54,8 +54,9 @@ public class CliContext {
@JsonProperty("igs")
private List igs = new ArrayList();
- @JsonProperty("questionnaires")
- private List questionnaires = new ArrayList();
+ @JsonProperty("questionnaire")
+ private Validator.QuestionnaireMode questionnaireMode = Validator.QuestionnaireMode.CHECK;
+
@JsonProperty("profiles")
private List profiles = new ArrayList();
@JsonProperty("sources")
@@ -118,22 +119,14 @@ public class CliContext {
return this;
}
- @JsonProperty("questionnaires")
- public List getQuestionnaires() {
- return questionnaires;
+ @JsonProperty("questionnaire")
+ public Validator.QuestionnaireMode getQuestionnaireMode() {
+ return questionnaireMode;
}
- @JsonProperty("questionnaires")
- public CliContext setQuestionnaires(List questionnaires) {
- this.questionnaires = questionnaires;
- return this;
- }
-
- public CliContext addQuestionnaire(String questionnaire) {
- if (this.questionnaires == null) {
- this.questionnaires = new ArrayList<>();
- }
- this.questionnaires.add(questionnaire);
+ @JsonProperty("questionnaire")
+ public CliContext setQuestionnaireMode(Validator.QuestionnaireMode questionnaireMode) {
+ this.questionnaireMode = questionnaireMode;
return this;
}
@@ -482,7 +475,7 @@ public class CliContext {
Objects.equals(snomedCT, that.snomedCT) &&
Objects.equals(targetVer, that.targetVer) &&
Objects.equals(igs, that.igs) &&
- Objects.equals(questionnaires, that.questionnaires) &&
+ Objects.equals(questionnaireMode, that.questionnaireMode) &&
Objects.equals(profiles, that.profiles) &&
Objects.equals(sources, that.sources) &&
Objects.equals(crumbTrails, that.crumbTrails) &&
@@ -494,6 +487,6 @@ public class CliContext {
@Override
public int hashCode() {
- return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, map, output, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaires, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
+ return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, map, output, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
}
}
\ No newline at end of file
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java
index 9626987e7..0dd0b3412 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java
@@ -14,9 +14,9 @@ import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
-import org.hl7.fhir.utilities.cache.BasePackageCacheManager;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.NpmPackage;
+import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
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 5ec8f9b56..0b8580e40 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
@@ -203,7 +203,7 @@ public class ValidationService {
validator.loadIg(src, cliContext.isRecursive());
}
System.out.print(" Get set... ");
- validator.setQuestionnaires(cliContext.getQuestionnaires());
+ validator.setQuestionnaireMode(cliContext.getQuestionnaireMode());
validator.setNative(cliContext.isDoNative());
validator.setHintAboutNonMustSupport(cliContext.isHintAboutNonMustSupport());
validator.setAnyExtensionsAllowed(cliContext.isAnyExtensionsAllowed());
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Display.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Display.java
index a57040513..09397e776 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Display.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Display.java
@@ -2,8 +2,8 @@ package org.hl7.fhir.validation.cli.utils;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.utilities.VersionUtilities;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import java.io.IOException;
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 68638cdfc..20211de73 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
@@ -122,8 +122,10 @@ public class Params {
} else if (args[i].equals(QUESTIONNAIRE)) {
if (i + 1 == args.length)
throw new Error("Specified -questionnaire without indicating questionnaire file");
- else
- cliContext.addQuestionnaire(args[++i]);
+ else {
+ String q = args[++i];
+ cliContext.setQuestionnaireMode(Validator.QuestionnaireMode.valueOf(q));
+ }
} else if (args[i].equals(NATIVE)) {
cliContext.setDoNative(true);
} else if (args[i].equals(ASSUME_VALID_REST_REF)) {
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 5f641c3c9..e42434539 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
@@ -140,6 +140,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.validation.BaseValidator;
+import org.hl7.fhir.validation.Validator.QuestionnaireMode;
import org.hl7.fhir.validation.instance.type.BundleValidator;
import org.hl7.fhir.validation.instance.type.CodeSystemValidator;
import org.hl7.fhir.validation.instance.type.MeasureValidator;
@@ -225,7 +226,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
@Override
- public List executeFunction(Object appContext, String functionName, List> parameters) {
+ public List executeFunction(Object appContext, List focus, String functionName, List> parameters) {
throw new Error(context.formatMessage(I18nConstants.NOT_DONE_YET_VALIDATORHOSTSERVICESEXECUTEFUNCTION));
}
@@ -375,6 +376,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean crumbTrails;
private List bundleValidationRules = new ArrayList<>();
private boolean validateValueSetCodesOnTxServer = true;
+ private QuestionnaireMode questionnaireMode;
public InstanceValidator(IWorkerContext theContext, IEvaluationContext hostServices) {
super(theContext);
@@ -483,7 +485,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean isKnownExtension(String url) {
// Added structuredefinition-expression and following extensions explicitly because they weren't defined in the version of the spec they need to be used with
- if ((allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression") || url.equals(VersionConvertorConstants.IG_DEPENDSON_PACKAGE_EXTENSION))
+ if ((allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression"))
return true;
for (String s : extensionDomains)
if (url.startsWith(s))
@@ -1521,6 +1523,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (extensionUrl.equals(profile.getUrl())) {
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", hasExtensionSlice(profile, url), I18nConstants.EXTENSION_EXT_SUBEXTENSION_INVALID, url, profile.getUrl());
}
+ } else if (SpecialExtensions.isKnownExtension(url)) {
+ ex = SpecialExtensions.getDefinition(url);
} else if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowUnknownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN_NOTHERE, url)) {
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, isKnownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN, url);
}
@@ -1556,6 +1560,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return ex;
}
+
private boolean hasExtensionSlice(StructureDefinition profile, String sliceName) {
for (ElementDefinition ed : profile.getSnapshot().getElement()) {
if (ed.getPath().equals("Extension.extension.url") && ed.hasFixed() && sliceName.equals(ed.getFixed().primitiveValue())) {
@@ -1933,7 +1938,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (fetcher != null) {
boolean found;
try {
- found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
+ found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url) ||
+ SpecialExtensions.isKnownExtension(url);
} catch (IOException e1) {
found = false;
}
@@ -3840,9 +3846,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (element.getType().equals("Observation")) {
validateObservation(errors, element, stack);
} else if (element.getType().equals("Questionnaire")) {
- new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker).validateQuestionannaire(errors, element, element, stack);
+ new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode).validateQuestionannaire(errors, element, element, stack);
} else if (element.getType().equals("QuestionnaireResponse")) {
- new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker).validateQuestionannaireResponse(hostContext, errors, element, stack);
+ new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode).validateQuestionannaireResponse(hostContext, errors, element, stack);
} else if (element.getType().equals("Measure")) {
new MeasureValidator(context, timeTracker).validateMeasure(hostContext, errors, element, stack);
} else if (element.getType().equals("MeasureReport")) {
@@ -3943,15 +3949,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private void validateContains(ValidatorHostContext hostContext, List errors, String path, ElementDefinition child, ElementDefinition context, Element resource, Element element, NodeStack stack, IdStatus idstatus) throws FHIRException {
String resourceName = element.getType();
TypeRefComponent trr = null;
+ CommaSeparatedStringBuilder bt = new CommaSeparatedStringBuilder();
for (TypeRefComponent tr : child.getType()) {
- if (tr.getCode().equals("Resource")) {
+ bt.append(tr.getCode());
+ if (tr.getCode().equals("Resource") || tr.getCode().equals(resourceName) ) {
trr = tr;
break;
}
}
stack.qualifyPath(".ofType("+resourceName+")");
if (trr == null) {
- rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName);
+ rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName, bt.toString());
} else if (isValidResourceType(resourceName, trr)) {
// special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise
ValidatorHostContext hc = null;
@@ -4002,7 +4010,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
private boolean isValidResourceType(String type, TypeRefComponent def) {
- if (!def.hasProfile()) {
+ if (!def.hasProfile() && def.getCode().equals("Resource")) {
+ return true;
+ }
+ if (def.getCode().equals(type)) {
return true;
}
List list = new ArrayList<>();
@@ -5072,4 +5083,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
+ public void setQuestionnaireMode(QuestionnaireMode questionnaireMode) {
+ this.questionnaireMode = questionnaireMode;
+ }
+
+ public QuestionnaireMode getQuestionnaireMode() {
+ return questionnaireMode;
+ }
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java
new file mode 100644
index 000000000..a51f75ef1
--- /dev/null
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java
@@ -0,0 +1,39 @@
+package org.hl7.fhir.validation.instance;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.hl7.fhir.convertors.VersionConvertorConstants;
+import org.hl7.fhir.exceptions.FHIRFormatError;
+import org.hl7.fhir.r5.formats.JsonParser;
+import org.hl7.fhir.r5.formats.XmlParser;
+import org.hl7.fhir.r5.model.StructureDefinition;
+import org.hl7.fhir.utilities.Utilities;
+
+public class SpecialExtensions {
+
+ // copied from R5 spec
+ private static final String MUST_SUPPORT_SOURCE = "{\"resourceType\" : \"StructureDefinition\",\"id\" : \"elementdefinition-type-must-support\",\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg\",\"valueCode\" : \"fhir\"},{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm\",\"valueInteger\" : 1}],\"url\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\",\"version\" : \"4.5.0\",\"name\" : \"type-must-support\",\"status\" : \"draft\",\"date\" : \"2015-02-28\",\"publisher\" : \"Health Level Seven, Inc. - FHIR Core WG\",\"contact\" : [{\"telecom\" : [{\"system\" : \"url\",\"value\" : \"http://hl7.org/special/committees/FHIR\"}]}],\"description\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"fhirVersion\" : \"4.5.0\",\"mapping\" : [{\"identity\" : \"rim\",\"uri\" : \"http://hl7.org/v3\",\"name\" : \"RIM Mapping\"}],\"kind\" : \"complex-type\",\"abstract\" : false,\"context\" : [{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type\"},{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type.profile\"},{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type.targetProfile\"}],\"type\" : \"Extension\",\"baseDefinition\" : \"http://hl7.org/fhir/StructureDefinition/Extension\",\"derivation\" : \"constraint\",\"snapshot\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"An element may be labelled as must support. This extension clarifies which types/profiles/targetProfiles are must-support. It has no meaning if the element itself is not must-support. If the element is labelled must-support, and none of the options are labelled as must support, then an application must support at least one of the possible options, but is not required to support all of them.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension\",\"min\" : 0,\"max\" : \"*\"},\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false},{\"id\" : \"Extension.id\",\"path\" : \"Extension.id\",\"representation\" : [\"xmlAttr\"],\"short\" : \"Unique id for inter-element referencing\",\"definition\" : \"Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Element.id\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"string\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"n/a\"}]},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"slicing\" : {\"discriminator\" : [{\"type\" : \"value\",\"path\" : \"url\"}],\"description\" : \"Extensions are always sliced by (at least) url\",\"rules\" : \"open\"},\"short\" : \"Extension\",\"definition\" : \"An Extension\",\"min\" : 0,\"max\" : \"0\",\"base\" : {\"path\" : \"Element.extension\",\"min\" : 0,\"max\" : \"*\"},\"type\" : [{\"code\" : \"Extension\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), \\\"value\\\")])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false,\"isSummary\" : false},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"representation\" : [\"xmlAttr\"],\"short\" : \"identifies the meaning of the extension\",\"definition\" : \"Source of the definition for the extension code - a logical name or a URL.\",\"comment\" : \"The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.url\",\"min\" : 1,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"uri\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\",\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"short\" : \"Value of extension\",\"definition\" : \"Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.value[x]\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"code\" : \"boolean\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]}]},\"differential\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"An element may be labelled as must support. This extension clarifies which types/profiles/targetProfiles are must-support. It has no meaning if the element itself is not must-support. If the element is labelled must-support, and none of the options are labelled as must support, then an application must support at least one of the possible options, but is not required to support all of them.\",\"min\" : 0,\"max\" : \"1\"},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"max\" : \"0\"},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\"},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"min\" : 1,\"type\" : [{\"code\" : \"boolean\"}]}]}}";
+
+ public static boolean isKnownExtension(String url) {
+ return Utilities.existsInList(url,
+ "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support"
+ );
+ }
+
+ public static StructureDefinition getDefinition(String url) {
+ try {
+ switch (url) {
+ case "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support" : return makeMustSupport();
+ default: return null;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private static StructureDefinition makeMustSupport() throws FHIRFormatError, IOException {
+ return (StructureDefinition) new JsonParser().parse(MUST_SUPPORT_SOURCE);
+ }
+
+}
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java
index 492a689af..d37ffa2a1 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java
@@ -45,6 +45,7 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.TimeTracker;
+import org.hl7.fhir.validation.Validator.QuestionnaireMode;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator.QStack;
import org.hl7.fhir.validation.instance.utils.NodeStack;
@@ -56,13 +57,15 @@ public class QuestionnaireValidator extends BaseValidator {
private EnableWhenEvaluator myEnableWhenEvaluator;
private FHIRPathEngine fpe;
+ private QuestionnaireMode questionnaireMode;
- public QuestionnaireValidator(IWorkerContext context, EnableWhenEvaluator myEnableWhenEvaluator, FHIRPathEngine fpe, TimeTracker timeTracker) {
+ public QuestionnaireValidator(IWorkerContext context, EnableWhenEvaluator myEnableWhenEvaluator, FHIRPathEngine fpe, TimeTracker timeTracker, QuestionnaireMode questionnaireMode) {
super(context);
source = Source.InstanceValidator;
this.myEnableWhenEvaluator = myEnableWhenEvaluator;
this.fpe = fpe;
this.timeTracker = timeTracker;
+ this.questionnaireMode = questionnaireMode;
}
public void validateQuestionannaire(List errors, Element element, Element element2, NodeStack stack) {
@@ -164,6 +167,9 @@ public class QuestionnaireValidator extends BaseValidator {
}
public void validateQuestionannaireResponse(ValidatorHostContext hostContext, List errors, Element element, NodeStack stack) throws FHIRException {
+ if (questionnaireMode == QuestionnaireMode.NONE) {
+ return;
+ }
Element q = element.getNamedChild("questionnaire");
String questionnaire = null;
if (q != null) {
@@ -179,9 +185,15 @@ public class QuestionnaireValidator extends BaseValidator {
questionnaire = q.getChildValue("reference");
}
}
- if (hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE)) {
+ boolean ok = questionnaireMode == QuestionnaireMode.REQUIRED ?
+ rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE) :
+ hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE);
+ if (ok) {
Questionnaire qsrc = questionnaire.startsWith("#") ? loadQuestionnaire(element, questionnaire.substring(1)) : context.fetchResource(Questionnaire.class, questionnaire);
- if (warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire)) {
+ ok = questionnaireMode == QuestionnaireMode.REQUIRED ?
+ rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire) :
+ warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
+ if (ok) {
boolean inProgress = "in-progress".equals(element.getNamedChildValue("status"));
validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element));
}
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java
index d7dec41cd..f7631ef8b 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java
@@ -28,6 +28,7 @@ import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.SearchParameter;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
+import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
@@ -95,6 +96,69 @@ public class StructureDefinitionValidator extends BaseValidator {
} catch (FHIRException | IOException e) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
}
+ List differentials = src.getChildrenByName("differential");
+ List snapshots = src.getChildrenByName("snapshot");
+ for (Element differential : differentials) {
+ validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0);
+ }
+ for (Element snapshot : snapshots) {
+ validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true);
+ }
+ }
+
+ private void validateElementList(List errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot) {
+ List elements = elementList.getChildrenByName("element");
+ int cc = 0;
+ for (Element element : elements) {
+ validateElementDefinition(errors, element, stack.push(element, cc, null, null), snapshot, hasSnapshot);
+ cc++;
+ }
+ }
+
+ private void validateElementDefinition(List errors, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot) {
+ boolean typeMustSupport = false;
+ List types = element.getChildrenByName("type");
+ for (Element type : types) {
+ if (hasMustSupportExtension(type)) {
+ typeMustSupport = true;
+ }
+ }
+ if (typeMustSupport) {
+ if (snapshot) {
+ rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_SNAPSHOT, element.getNamedChildValue("path"));
+ } else {
+ hint(errors, IssueType.EXCEPTION, stack.getLiteralPath(), hasSnapshot || "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_DIFF, element.getNamedChildValue("path"));
+ }
+ }
+ }
+
+ private boolean hasMustSupportExtension(Element type) {
+ if ("true".equals(getExtensionValue(type, ToolingExtensions.EXT_MUST_SUPPORT))) {
+ return true;
+ }
+ List profiles = type.getChildrenByName("profile");
+ for (Element profile : profiles) {
+ if ("true".equals(getExtensionValue(profile, ToolingExtensions.EXT_MUST_SUPPORT))) {
+ return true;
+ }
+ }
+ profiles = type.getChildrenByName("targetProfile");
+ for (Element profile : profiles) {
+ if ("true".equals(getExtensionValue(profile, ToolingExtensions.EXT_MUST_SUPPORT))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private String getExtensionValue(Element element, String url) {
+ List extensions = element.getChildrenByName("extension");
+ for (Element extension : extensions) {
+ if (url.equals(extension.getNamedChildValue("url"))) {
+ return extension.getNamedChildValue("value");
+ }
+ }
+ return null;
}
private StructureDefinition loadAsSD(Element src) throws FHIRException, IOException {
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java
index a10173f81..b3d4c0e3c 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java
@@ -56,28 +56,28 @@ public class ValueSetValidator extends BaseValidator {
List composes = vs.getChildrenByName("compose");
int cc = 0;
for (Element compose : composes) {
- validateValueSetCompose(errors, compose, stack.push(compose, cc, null, null), vs.getNamedChildValue("url"));
+ validateValueSetCompose(errors, compose, stack.push(compose, cc, null, null), vs.getNamedChildValue("url"), "retired".equals(vs.getNamedChildValue("url")));
cc++;
}
}
}
- private void validateValueSetCompose(List errors, Element compose, NodeStack stack, String vsid) {
+ private void validateValueSetCompose(List errors, Element compose, NodeStack stack, String vsid, boolean retired) {
List includes = compose.getChildrenByName("include");
int ci = 0;
for (Element include : includes) {
- validateValueSetInclude(errors, include, stack.push(include, ci, null, null), vsid);
+ validateValueSetInclude(errors, include, stack.push(include, ci, null, null), vsid, retired);
ci++;
}
List excludes = compose.getChildrenByName("exclude");
int ce = 0;
for (Element exclude : excludes) {
- validateValueSetInclude(errors, exclude, stack.push(exclude, ce, null, null), vsid);
+ validateValueSetInclude(errors, exclude, stack.push(exclude, ce, null, null), vsid, retired);
ce++;
}
}
- private void validateValueSetInclude(List errors, Element include, NodeStack stack, String vsid) {
+ private void validateValueSetInclude(List errors, Element include, NodeStack stack, String vsid, boolean retired) {
String system = include.getChildValue("system");
String version = include.getChildValue("version");
List valuesets = include.getChildrenByName("valueSet");
@@ -125,9 +125,9 @@ public class ValueSetValidator extends BaseValidator {
}
for (VSCodingValidationRequest cv : batch) {
if (version == null) {
- warning(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, cv.getCoding().getCode());
+ warningOrHint(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, cv.getCoding().getCode());
} else {
- warning(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, cv.getCoding().getCode());
+ warningOrHint(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, cv.getCoding().getCode());
}
}
}
diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/packages/PackageValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/packages/PackageValidator.java
index 099f203c8..6304f71d4 100644
--- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/packages/PackageValidator.java
+++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/packages/PackageValidator.java
@@ -7,11 +7,11 @@ import java.util.List;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.utilities.VersionUtilities;
-import org.hl7.fhir.utilities.cache.NpmPackage;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.CachingPackageClient;
-import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.npm.CachingPackageClient;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.NpmPackage;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
+import org.hl7.fhir.utilities.npm.PackageClient.PackageInfo;
public class PackageValidator {
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java
index 367977e38..d0cdf5425 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java
@@ -38,9 +38,9 @@ import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
-import org.hl7.fhir.utilities.cache.NpmPackage;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.NpmPackage;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java
index 03a5ba941..ba1bcce23 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java
@@ -22,8 +22,8 @@ import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.junit.jupiter.api.Disabled;
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java
index 030352c40..8b616af25 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java
@@ -334,7 +334,7 @@ public class SnapShotGenerationXTests {
}
@Override
- public List executeFunction(Object appContext, String functionName, List> parameters) {
+ public List executeFunction(Object appContext, List focus, String functionName, List> parameters) {
if ("fixture".equals(functionName)) {
String id = fp.convertToString(parameters.get(0));
Resource res = fetchFixture(id);
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java
index 0cb9c8016..1e65b8cb7 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java
@@ -59,9 +59,8 @@ import org.hl7.fhir.utilities.CSFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
-import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
-import org.hl7.fhir.utilities.cache.ToolsVersion;
-
+import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
+import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java
index 7dc58c52c..7c8671c66 100644
--- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java
+++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java
@@ -435,7 +435,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
}
@Override
- public List executeFunction(Object appContext, String functionName, List> parameters) {
+ public List executeFunction(Object appContext, List focus, String functionName, List> parameters) {
return null;
}
diff --git a/pom.xml b/pom.xml
index 29be4c280..8e975d598 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,19 +13,18 @@
each other. It is fine to bump the point version of this POM without affecting
HAPI FHIR.
-->
- 5.1.11-SNAPSHOT
+ org.hl7.fhir.core
+ 5.1.17-SNAPSHOT
+ pom
5.1.0
- 1.1.40
+ 1.1.45
5.6.2
3.0.0-M4
0.8.5
- org.hl7.fhir.core
- pom
-
HL7 Core Artifacts
@@ -47,13 +46,6 @@
org.hl7.fhir.report
-
-
- ossrh
- https://oss.sonatype.org/content/repositories/snapshots
-
-
-
@@ -318,17 +310,6 @@
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.7
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
-
org.apache.maven.plugins
maven-deploy-plugin
@@ -338,7 +319,23 @@
- deploy
+ github-repo
+
+ false
+
+ deployToGitHub
+
+
+
+
+ github
+ https://maven.pkg.github.com/hapifhir/org.hl7.fhir.core
+
+
+ github
+ https://maven.pkg.github.com/hapifhir/org.hl7.fhir.core
+
+
@@ -362,5 +359,57 @@
+
+ ossrh-repo
+
+ false
+
+ deployToSonatype
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.7
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+ ${gpg.keyname}
+ ${gpg.keyname}
+
+
+
+
+
+
+