Merge pull request #691 from hapifhir/gg-202112-sd-derivation
Gg 202112 sd derivation
This commit is contained in:
commit
a3de3cebf5
|
@ -0,0 +1,6 @@
|
|||
Validator:
|
||||
* check StructureDefinition derivation consistency
|
||||
* fix bug looking for contained resources inside bundles
|
||||
|
||||
Other code changes:
|
||||
* Add support for new FHIR releases
|
|
@ -0,0 +1,188 @@
|
|||
package org.hl7.fhir.convertors.analytics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.utilities.SimpleHTTPClient;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
|
||||
import org.hl7.fhir.utilities.json.JSONUtil;
|
||||
import org.hl7.fhir.utilities.json.JsonTrackingParser;
|
||||
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.PackageInfo;
|
||||
import org.hl7.fhir.utilities.npm.ToolsVersion;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class PackageVisitor {
|
||||
|
||||
public interface IPackageVisitorProcessor {
|
||||
public void processResource(String pid, String version, String type, byte[] content) throws FHIRException;
|
||||
}
|
||||
|
||||
private List<String> resourceTypes = new ArrayList<>();
|
||||
private List<String> versions = new ArrayList<>();
|
||||
private boolean corePackages;
|
||||
private boolean oldVersions;
|
||||
private IPackageVisitorProcessor processor;
|
||||
private FilesystemPackageCacheManager pcm;
|
||||
private PackageClient pc;
|
||||
|
||||
public List<String> getResourceTypes() {
|
||||
return resourceTypes;
|
||||
}
|
||||
|
||||
public void setResourceTypes(List<String> resourceTypes) {
|
||||
this.resourceTypes = resourceTypes;
|
||||
}
|
||||
|
||||
public List<String> getVersions() {
|
||||
return versions;
|
||||
}
|
||||
|
||||
public void setVersions(List<String> versions) {
|
||||
this.versions = versions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean isCorePackages() {
|
||||
return corePackages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setCorePackages(boolean corePackages) {
|
||||
this.corePackages = corePackages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean isOldVersions() {
|
||||
return oldVersions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setOldVersions(boolean oldVersions) {
|
||||
this.oldVersions = oldVersions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public IPackageVisitorProcessor getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public void setProcessor(IPackageVisitorProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public void visitPackages() throws IOException, ParserConfigurationException, SAXException {
|
||||
System.out.println("Finding packages");
|
||||
pc = new PackageClient(PackageClient.PRIMARY_SERVER);
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
Set<String> pidList = getAllPackages();
|
||||
System.out.println("Go: "+pidList.size()+" packages");
|
||||
for (String pid : pidList) {
|
||||
List<String> vList = listVersions(pid);
|
||||
if (oldVersions) {
|
||||
for (String v : vList) {
|
||||
processPackage(pid, v);
|
||||
}
|
||||
} else if (vList.isEmpty()) {
|
||||
System.out.println("No Packages for "+pid);
|
||||
} else {
|
||||
processPackage(pid, vList.get(vList.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> listVersions(String pid) throws IOException {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (pid !=null) {
|
||||
for (PackageInfo i : pc.getVersions(pid)) {
|
||||
list.add(i.getVersion());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Set<String> getAllPackages() throws IOException, ParserConfigurationException, SAXException {
|
||||
Set<String> list = new HashSet<>();
|
||||
for (PackageInfo i : pc.search(null, null, null, false)) {
|
||||
list.add(i.getId());
|
||||
}
|
||||
JsonObject json = JsonTrackingParser.fetchJson("https://raw.githubusercontent.com/FHIR/ig-registry/master/fhir-ig-list.json");
|
||||
for (JsonObject ig : JSONUtil.objects(json, "guides")) {
|
||||
list.add(JSONUtil.str(ig, "npm-name"));
|
||||
}
|
||||
json = JsonTrackingParser.fetchJson("https://raw.githubusercontent.com/FHIR/ig-registry/master/package-feeds.json");
|
||||
for (JsonObject feed : JSONUtil.objects(json, "feeds")) {
|
||||
processFeed(list, JSONUtil.str(feed, "url"));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void processFeed(Set<String> list, String str) throws IOException, ParserConfigurationException, SAXException {
|
||||
System.out.println("Feed "+str);
|
||||
try {
|
||||
SimpleHTTPClient fetcher = new SimpleHTTPClient();
|
||||
HTTPResult res = fetcher.get(str+"?nocache=" + System.currentTimeMillis());
|
||||
res.checkThrowException();
|
||||
Document xml = XMLUtil.parseToDom(res.getContent());
|
||||
for (Element channel : XMLUtil.getNamedChildren(xml.getDocumentElement(), "channel")) {
|
||||
for (Element item : XMLUtil.getNamedChildren(channel, "item")) {
|
||||
String pid = XMLUtil.getNamedChildText(item, "title");
|
||||
if (pid.contains("#")) {
|
||||
list.add(pid.substring(0, pid.indexOf("#")));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processPackage(String pid, String v) throws IOException {
|
||||
NpmPackage npm = null;
|
||||
String fv = null;
|
||||
try {
|
||||
npm = pcm.loadPackage(pid, v);
|
||||
fv = npm.fhirVersion();
|
||||
} catch (Throwable e) {
|
||||
System.out.println("Unable to process: "+pid+"#"+v+": "+e.getMessage());
|
||||
}
|
||||
int c = 0;
|
||||
if (fv != null && (versions.isEmpty() || versions.contains(fv))) {
|
||||
for (String type : resourceTypes) {
|
||||
for (String s : npm.listResources(type)) {
|
||||
c++;
|
||||
processor.processResource(pid+"#"+v, fv, type, TextFile.streamToBytes(npm.load("package", s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Processed: "+pid+"#"+v+": "+c+" resources");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
package org.hl7.fhir.convertors.analytics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.hl7.fhir.convertors.analytics.PackageVisitor.IPackageVisitorProcessor;
|
||||
import org.hl7.fhir.dstu2.model.SearchParameter;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class SearchParameterAnalysis implements IPackageVisitorProcessor {
|
||||
|
||||
public static class SearchParameterTypeUsage {
|
||||
private Set<String> coreUsage = new HashSet<>();
|
||||
private Set<String> igUsage = new HashSet<>();
|
||||
public String summary() {
|
||||
return ""+coreUsage.size()+" / "+igUsage.size();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchParameterType {
|
||||
private Map<String, SearchParameterTypeUsage> usages = new HashMap<>();
|
||||
public void seeUsage(boolean core, String usage, String url) {
|
||||
if (!usages.containsKey(usage)) {
|
||||
usages.put(usage, new SearchParameterTypeUsage());
|
||||
}
|
||||
SearchParameterTypeUsage tu = usages.get(usage);
|
||||
if (core) {
|
||||
tu.coreUsage.add(url);
|
||||
} else {
|
||||
tu.igUsage.add(url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchParameterVersionAnalysis {
|
||||
private Map<String, SearchParameterType> types = new HashMap<>();
|
||||
private String version;
|
||||
|
||||
public void seeUsage(boolean core, String type, String usage, String url) {
|
||||
// System.out.println("v"+version+" "+Utilities.padRight(url, ' ', 60)+" "+type+"/"+usage);
|
||||
if (type == null) {
|
||||
type = "n/a";
|
||||
}
|
||||
if (usage == null) {
|
||||
usage = "n/a";
|
||||
}
|
||||
if (!types.containsKey(type)) {
|
||||
types.put(type, new SearchParameterType());
|
||||
}
|
||||
SearchParameterType tu = types.get(type);
|
||||
tu.seeUsage(core, usage, url);
|
||||
}
|
||||
|
||||
public void printSummary() {
|
||||
Set<String> usages = new HashSet<>();
|
||||
for (SearchParameterType tu : types.values()) {
|
||||
usages.addAll(tu.usages.keySet());
|
||||
}
|
||||
List<String> ul = new ArrayList<String>();
|
||||
ul.addAll(usages);
|
||||
Collections.sort(ul);
|
||||
System.out.print(Utilities.padRight("", ' ', 10));
|
||||
for (String u : ul) {
|
||||
System.out.print(Utilities.padRight(u, ' ', 10));
|
||||
}
|
||||
System.out.println();
|
||||
for (String t : types.keySet()) {
|
||||
System.out.print(Utilities.padRight(t, ' ', 10));
|
||||
SearchParameterType tu = types.get(t);
|
||||
for (String u : ul) {
|
||||
SearchParameterTypeUsage uu = tu.usages.get(u);
|
||||
if (uu == null) {
|
||||
System.out.print(Utilities.padRight("0 / 0", ' ', 10));
|
||||
} else {
|
||||
System.out.print(Utilities.padRight(uu.summary(), ' ', 10));
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Map<String, SearchParameterVersionAnalysis> versions = new HashMap<String, SearchParameterAnalysis.SearchParameterVersionAnalysis>();
|
||||
|
||||
@Override
|
||||
public void processResource(String pid, String version, String type, byte[] content) throws FHIRException {
|
||||
// System.out.println("v"+version+" "+type+" from "+pid);
|
||||
boolean core = pid.startsWith("hl7.fhir.r") && (pid.contains(".core") || pid.contains(".examples"));
|
||||
version = VersionUtilities.getMajMin(version);
|
||||
if (!versions.containsKey(version)) {
|
||||
versions.put(version, new SearchParameterVersionAnalysis());
|
||||
versions.get(version).version = version;
|
||||
}
|
||||
try {
|
||||
if (VersionUtilities.isR5Ver(version)) {
|
||||
processR5SP(core, versions.get(version), content);
|
||||
} else if (VersionUtilities.isR4BVer(version)) {
|
||||
processR4SP(core, versions.get(version), content);
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
processR4SP(core, versions.get(version), content);
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
processR3SP(core, versions.get(version), content);
|
||||
} else if (VersionUtilities.isR2Ver(version)) {
|
||||
processR2SP(core, versions.get(version), content);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void processR5SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException {
|
||||
org.hl7.fhir.r5.model.Resource res = new org.hl7.fhir.r5.formats.JsonParser().parse(content);
|
||||
if (res instanceof org.hl7.fhir.r5.model.Bundle) {
|
||||
for (org.hl7.fhir.r5.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.r5.model.Bundle) res).getEntry()) {
|
||||
if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.r5.model.SearchParameter) {
|
||||
org.hl7.fhir.r5.model.SearchParameter sp = (org.hl7.fhir.r5.model.SearchParameter) bnd.getResource();
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
org.hl7.fhir.r5.model.SearchParameter sp = (org.hl7.fhir.r5.model.SearchParameter) res;
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
private void processR4SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException {
|
||||
org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(content);
|
||||
if (res instanceof org.hl7.fhir.r4.model.Bundle) {
|
||||
for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.r4.model.Bundle) res).getEntry()) {
|
||||
if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.r4.model.SearchParameter) {
|
||||
org.hl7.fhir.r4.model.SearchParameter sp = (org.hl7.fhir.r4.model.SearchParameter) bnd.getResource();
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
org.hl7.fhir.r4.model.SearchParameter sp = (org.hl7.fhir.r4.model.SearchParameter) res;
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
private void processR3SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException {
|
||||
org.hl7.fhir.dstu3.model.Resource res = new org.hl7.fhir.dstu3.formats.JsonParser().parse(content);
|
||||
if (res instanceof org.hl7.fhir.dstu3.model.Bundle) {
|
||||
for (org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.dstu3.model.Bundle) res).getEntry()) {
|
||||
if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.dstu3.model.SearchParameter) {
|
||||
org.hl7.fhir.dstu3.model.SearchParameter sp = (org.hl7.fhir.dstu3.model.SearchParameter) bnd.getResource();
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
org.hl7.fhir.dstu3.model.SearchParameter sp = (org.hl7.fhir.dstu3.model.SearchParameter) res;
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
private void processR2SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException {
|
||||
org.hl7.fhir.dstu2.model.Resource res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(content);
|
||||
if (res instanceof org.hl7.fhir.dstu2.model.Bundle) {
|
||||
for (org.hl7.fhir.dstu2.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.dstu2.model.Bundle) res).getEntry()) {
|
||||
if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.dstu2.model.SearchParameter) {
|
||||
org.hl7.fhir.dstu2.model.SearchParameter sp = (org.hl7.fhir.dstu2.model.SearchParameter) bnd.getResource();
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
org.hl7.fhir.dstu2.model.SearchParameter sp = (org.hl7.fhir.dstu2.model.SearchParameter) res;
|
||||
analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new SearchParameterAnalysis().execute();
|
||||
}
|
||||
|
||||
private void execute() throws IOException, ParserConfigurationException, SAXException {
|
||||
PackageVisitor pv = new PackageVisitor();
|
||||
pv.getResourceTypes().add("SearchParameter");
|
||||
pv.getResourceTypes().add("Bundle");
|
||||
pv.setOldVersions(false);
|
||||
pv.setCorePackages(true);
|
||||
pv.setProcessor(this);
|
||||
pv.visitPackages();
|
||||
|
||||
printSummary();
|
||||
}
|
||||
|
||||
private void printSummary() {
|
||||
for (String v : versions.keySet()) {
|
||||
System.out.println("-- v"+v+"---------------------");
|
||||
versions.get(v).printSummary();
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -10036,6 +10036,7 @@ The primary difference between a medication statement and a medication administr
|
|||
* R4B - manually added
|
||||
*/
|
||||
_4_1_0,
|
||||
_4_3_0_SNAPSHOT1,
|
||||
_4_3_0_CIBUILD,
|
||||
NULL;
|
||||
public static FHIRVersion fromCode(String codeString) throws FHIRException {
|
||||
|
@ -10089,7 +10090,9 @@ The primary difference between a medication statement and a medication administr
|
|||
return _4_0_1;
|
||||
if ("4.1.0".equals(codeString))
|
||||
return _4_1_0;
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return _4_3_0_SNAPSHOT1;
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return _4_3_0_CIBUILD;
|
||||
throw new FHIRException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
|
@ -10123,7 +10126,8 @@ The primary difference between a medication statement and a medication administr
|
|||
case _4_0_0: return "4.0.0";
|
||||
case _4_0_1: return "4.0.1";
|
||||
case _4_1_0: return "4.1.0";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-CIBUILD";
|
||||
case _4_3_0_SNAPSHOT1: return "4.3.0-snapshot1";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-cibuild";
|
||||
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
|
@ -10155,6 +10159,7 @@ The primary difference between a medication statement and a medication administr
|
|||
case _4_0_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_0_1: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_1_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_3_0_SNAPSHOT1: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_3_0_CIBUILD: return "http://hl7.org/fhir/FHIR-version";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
|
@ -10186,6 +10191,7 @@ The primary difference between a medication statement and a medication administr
|
|||
case _4_0_0: return "FHIR Release 4 (Normative + STU).";
|
||||
case _4_0_1: return "FHIR Release 4 Technical Correction #1.";
|
||||
case _4_1_0: return "FHIR Release 4B Ballot #1";
|
||||
case _4_3_0_SNAPSHOT1: return "FHIR Release 4B Snapshot #1";
|
||||
case _4_3_0_CIBUILD: return "FHIR Release 4B CI-Builld";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
|
@ -10217,7 +10223,8 @@ The primary difference between a medication statement and a medication administr
|
|||
case _4_0_0: return "4.0.0";
|
||||
case _4_0_1: return "4.0.1";
|
||||
case _4_1_0: return "4.1.0";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-CIBUILD";
|
||||
case _4_3_0_SNAPSHOT1: return "4.3.0-snapshot";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-cibuild";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
|
@ -10283,7 +10290,9 @@ The primary difference between a medication statement and a medication administr
|
|||
return FHIRVersion._4_0_1;
|
||||
if ("4.1.0".equals(codeString))
|
||||
return FHIRVersion._4_1_0;
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return FHIRVersion._4_3_0_SNAPSHOT1;
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return FHIRVersion._4_3_0_CIBUILD;
|
||||
throw new IllegalArgumentException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
|
@ -10343,7 +10352,9 @@ The primary difference between a medication statement and a medication administr
|
|||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_0_1);
|
||||
if ("4.1.0".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_1_0);
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_3_0_SNAPSHOT1);
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_3_0_CIBUILD);
|
||||
throw new FHIRException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
|
@ -10396,8 +10407,10 @@ The primary difference between a medication statement and a medication administr
|
|||
return "4.0.1";
|
||||
if (code == FHIRVersion._4_1_0)
|
||||
return "4.1.0";
|
||||
if (code == FHIRVersion._4_3_0_SNAPSHOT1)
|
||||
return "4.3.0-snapshot1";
|
||||
if (code == FHIRVersion._4_3_0_CIBUILD)
|
||||
return "4.3.0_CIBUILD";
|
||||
return "4.3.0-cibuild";
|
||||
return "?";
|
||||
}
|
||||
public String toSystem(FHIRVersion code) {
|
||||
|
|
|
@ -6716,6 +6716,10 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
* R5 Preview #1.
|
||||
*/
|
||||
_4_2_0,
|
||||
/**
|
||||
* R4B
|
||||
*/
|
||||
_4_3_0_SNAPSHOT1,
|
||||
/**
|
||||
* R4B
|
||||
*/
|
||||
|
@ -6732,6 +6736,14 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
* R5 Draft Ballot.
|
||||
*/
|
||||
_4_6_0,
|
||||
/**
|
||||
* R5 CI Build.
|
||||
*/
|
||||
_5_0_0_SNAPSHOT1,
|
||||
/**
|
||||
* R5 CI Build.
|
||||
*/
|
||||
_5_0_0_CIBUILD,
|
||||
/**
|
||||
* added to help the parsers
|
||||
*/
|
||||
|
@ -6790,7 +6802,9 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
return _4_1_0;
|
||||
if ("4.2.0".equals(codeString))
|
||||
return _4_2_0;
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return _4_3_0_SNAPSHOT1;
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return _4_3_0_CIBUILD;
|
||||
if ("4.4.0".equals(codeString))
|
||||
return _4_4_0;
|
||||
|
@ -6798,6 +6812,10 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
return _4_5_0;
|
||||
if ("4.6.0".equals(codeString))
|
||||
return _4_6_0;
|
||||
if ("5.0.0-snapshot1".equals(codeString))
|
||||
return _5_0_0_SNAPSHOT1;
|
||||
if ("5.0.0-cibuild".equals(codeString))
|
||||
return _5_0_0_CIBUILD;
|
||||
throw new FHIRException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
public String toCode() {
|
||||
|
@ -6827,10 +6845,13 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
case _4_0_1: return "4.0.1";
|
||||
case _4_1_0: return "4.1.0";
|
||||
case _4_2_0: return "4.2.0";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-CIBUILD";
|
||||
case _4_3_0_SNAPSHOT1: return "4.3.0-snapshot1";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-cibuild";
|
||||
case _4_4_0: return "4.4.0";
|
||||
case _4_5_0: return "4.5.0";
|
||||
case _4_6_0: return "4.6.0";
|
||||
case _5_0_0_SNAPSHOT1: return "5.0.0-snapshot1";
|
||||
case _5_0_0_CIBUILD: return "5.0.0-cibuild";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
|
@ -6862,10 +6883,13 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
case _4_0_1: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_1_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_2_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_3_0_SNAPSHOT1: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_3_0_CIBUILD: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_4_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_5_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _4_6_0: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _5_0_0_SNAPSHOT1: return "http://hl7.org/fhir/FHIR-version";
|
||||
case _5_0_0_CIBUILD: return "http://hl7.org/fhir/FHIR-version";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
|
@ -6897,10 +6921,13 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
case _4_0_1: return "FHIR Release 4 (Normative + STU) with 1 technical errata.";
|
||||
case _4_1_0: return "Interim Version.";
|
||||
case _4_2_0: return "R5 Preview #1.";
|
||||
case _4_3_0_CIBUILD: return "R4B CIBuild";
|
||||
case _4_3_0_SNAPSHOT1: return "R4B Snapshot #1";
|
||||
case _4_3_0_CIBUILD: return "R4B Rolling CI-Build";
|
||||
case _4_4_0: return "R5 Preview #2.";
|
||||
case _4_5_0: return "R5 Preview #3.";
|
||||
case _4_6_0: return "R5 Draft Ballot.";
|
||||
case _4_6_0: return "R5 Draft Ballot";
|
||||
case _5_0_0_SNAPSHOT1: return "R5 Snapshot #1";
|
||||
case _5_0_0_CIBUILD: return "R5 Rooling CI-Build";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
|
@ -6932,10 +6959,13 @@ The MedicationUsage resource was previously called MedicationStatement.
|
|||
case _4_0_1: return "4.0.1";
|
||||
case _4_1_0: return "4.1.0";
|
||||
case _4_2_0: return "4.2.0";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-CIBUILD";
|
||||
case _4_3_0_SNAPSHOT1: return "4.3.0-snapshot1";
|
||||
case _4_3_0_CIBUILD: return "4.3.0-cibuild";
|
||||
case _4_4_0: return "4.4.0";
|
||||
case _4_5_0: return "4.5.0";
|
||||
case _4_6_0: return "4.6.0";
|
||||
case _5_0_0_SNAPSHOT1: return "5.0.0-snapshot1";
|
||||
case _5_0_0_CIBUILD: return "5.0.0-cibuild";
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
|
@ -6996,7 +7026,7 @@ public String toCode(int len) {
|
|||
return true;
|
||||
if ("4.2.0".equals(codeString))
|
||||
return true;
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -7069,7 +7099,9 @@ public String toCode(int len) {
|
|||
return FHIRVersion._4_1_0;
|
||||
if ("4.2.0".equals(codeString))
|
||||
return FHIRVersion._4_2_0;
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return FHIRVersion._4_3_0_SNAPSHOT1;
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return FHIRVersion._4_3_0_CIBUILD;
|
||||
if ("4.4.0".equals(codeString))
|
||||
return FHIRVersion._4_4_0;
|
||||
|
@ -7077,6 +7109,10 @@ public String toCode(int len) {
|
|||
return FHIRVersion._4_5_0;
|
||||
if ("4.6.0".equals(codeString))
|
||||
return FHIRVersion._4_6_0;
|
||||
if ("5.0.0-snapshot1".equals(codeString))
|
||||
return FHIRVersion._5_0_0_SNAPSHOT1;
|
||||
if ("5.0.0-cibuild".equals(codeString))
|
||||
return FHIRVersion._5_0_0_CIBUILD;
|
||||
throw new IllegalArgumentException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
public Enumeration<FHIRVersion> fromType(Base code) throws FHIRException {
|
||||
|
@ -7137,7 +7173,9 @@ public String toCode(int len) {
|
|||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_1_0);
|
||||
if ("4.2.0".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_2_0);
|
||||
if ("4.3.0-CIBUILD".equals(codeString))
|
||||
if ("4.3.0-snapshot1".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_3_0_SNAPSHOT1);
|
||||
if ("4.3.0-cibuild".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_3_0_CIBUILD);
|
||||
if ("4.4.0".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_4_0);
|
||||
|
@ -7145,6 +7183,10 @@ public String toCode(int len) {
|
|||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_5_0);
|
||||
if ("4.6.0".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._4_6_0);
|
||||
if ("5.0.0-snapshot1".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._5_0_0_SNAPSHOT1);
|
||||
if ("5.0.0-cibuild".equals(codeString))
|
||||
return new Enumeration<FHIRVersion>(this, FHIRVersion._5_0_0_CIBUILD);
|
||||
throw new FHIRException("Unknown FHIRVersion code '"+codeString+"'");
|
||||
}
|
||||
public String toCode(FHIRVersion code) {
|
||||
|
@ -7198,14 +7240,20 @@ public String toCode(int len) {
|
|||
return "4.1.0";
|
||||
if (code == FHIRVersion._4_2_0)
|
||||
return "4.2.0";
|
||||
if (code == FHIRVersion._4_3_0_SNAPSHOT1)
|
||||
return "4.3.0-snapshot1";
|
||||
if (code == FHIRVersion._4_3_0_CIBUILD)
|
||||
return "4.3.0-CIBUILD";
|
||||
return "4.3.0-cibuild";
|
||||
if (code == FHIRVersion._4_4_0)
|
||||
return "4.4.0";
|
||||
if (code == FHIRVersion._4_5_0)
|
||||
return "4.5.0";
|
||||
if (code == FHIRVersion._4_6_0)
|
||||
return "4.6.0";
|
||||
if (code == FHIRVersion._5_0_0_SNAPSHOT1)
|
||||
return "5.0.0-snapshot1";
|
||||
if (code == FHIRVersion._5_0_0_CIBUILD)
|
||||
return "5.0.0-cibuild";
|
||||
return "?";
|
||||
}
|
||||
public String toSystem(FHIRVersion code) {
|
||||
|
|
|
@ -796,7 +796,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
|
||||
if (vs != null && !vs.hasUrl()) {
|
||||
vs = vs.copy();
|
||||
vs.setUrl("urn:uuid:"+UUID.randomUUID().toString().toLowerCase());
|
||||
vs.setUrl(q.getUrl()+"--"+q.getContained(i.getAnswerValueSet().substring(1)));
|
||||
}
|
||||
} else {
|
||||
vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet());
|
||||
|
|
|
@ -613,8 +613,10 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
if (valueset.hasExpansion()) {
|
||||
return checkExpansion(new Coding(system, code, null));
|
||||
} else if (valueset.hasCompose()) {
|
||||
int i = 0;
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) {
|
||||
Boolean ok = inComponent(vsi, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
Boolean ok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
i++;
|
||||
if (ok == null && result == false) {
|
||||
result = null;
|
||||
} else if (ok) {
|
||||
|
@ -623,7 +625,8 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
}
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getExclude()) {
|
||||
Boolean nok = inComponent(vsi, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
Boolean nok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
i++;
|
||||
if (nok == null && result == false) {
|
||||
result = null;
|
||||
} else if (nok != null && nok) {
|
||||
|
@ -635,7 +638,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return result;
|
||||
}
|
||||
|
||||
private Boolean inComponent(ConceptSetComponent vsi, String system, String code, boolean only, List<String> warnings) throws FHIRException {
|
||||
private Boolean inComponent(ConceptSetComponent vsi, int vsiIndex, String system, String code, boolean only, List<String> warnings) throws FHIRException {
|
||||
for (UriType uri : vsi.getValueSet()) {
|
||||
if (inImport(uri.getValue(), system, code)) {
|
||||
return true;
|
||||
|
@ -662,7 +665,8 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
// make up a transient value set with
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setStatus(PublicationStatus.ACTIVE);
|
||||
vs.setUrl(Utilities.makeUuidUrn());
|
||||
vs.setUrl(valueset.getUrl()+"--"+vsiIndex);
|
||||
vs.setVersion(valueset.getVersion());
|
||||
vs.getCompose().addInclude(vsi);
|
||||
ValidationResult res = context.validateCode(options.noClient(), new Coding(system, code, null), vs);
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package org.hl7.fhir.r5.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemHierarchyMeaning;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
|
||||
public class ResourceFixer {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ResourceFixer().vistAllResources(args[0]);
|
||||
|
||||
}
|
||||
|
||||
private Set<String> refs = new HashSet<>();
|
||||
|
||||
private void vistAllResources(String folder) {
|
||||
|
||||
for (File f : new File(folder).listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
vistAllResources(f.getAbsolutePath());
|
||||
} else if (f.getName().endsWith(".json")) {
|
||||
Resource r = null;
|
||||
try {
|
||||
r = new JsonParser().parse(new FileInputStream(f));
|
||||
} catch (Throwable e) {
|
||||
// nothing at all
|
||||
}
|
||||
if (r != null) {
|
||||
try {
|
||||
if (visitResource(r)) {
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), r);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else if (f.getName().endsWith(".xml")) {
|
||||
Resource r = null;
|
||||
try {
|
||||
r = new XmlParser().parse(new FileInputStream(f));
|
||||
} catch (Throwable e) {
|
||||
// nothing at all
|
||||
}
|
||||
if (r != null) {
|
||||
try {
|
||||
if (visitResource(r)) {
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), r);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean visitResource(Resource r) {
|
||||
if (r.hasId()) {
|
||||
String ref = r.fhirType()+"/"+r.getId();
|
||||
if (refs.contains(ref)) {
|
||||
throw new FHIRException("Duplicate resource "+ref);
|
||||
}
|
||||
refs.add(ref);
|
||||
}
|
||||
if (r instanceof CodeSystem) {
|
||||
return visitCodeSystem((CodeSystem) r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean visitCodeSystem(CodeSystem cs) {
|
||||
if (!cs.hasContent()) {
|
||||
System.out.println("Setting content = complete for CodeSystem/"+cs.getId());
|
||||
cs.setContent(CodeSystemContentMode.COMPLETE);
|
||||
return true;
|
||||
} else if (!cs.hasHierarchyMeaning() && hasHierarchy(cs)) {
|
||||
System.out.println("Setting hierarchyMeaning = is-a for CodeSystem/"+cs.getId());
|
||||
cs.setHierarchyMeaning(CodeSystemHierarchyMeaning.ISA);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasHierarchy(CodeSystem cs) {
|
||||
for (ConceptDefinitionComponent c : cs.getConcept()) {
|
||||
if (c.hasConcept()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -361,6 +361,7 @@ public class I18nConstants {
|
|||
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 SD_DERIVATION_KIND_MISMATCH = "SD_DERIVATION_KIND_MISMATCH";
|
||||
public static final String SD_ED_TYPE_PROFILE_UNKNOWN = "SD_ED_TYPE_PROFILE_UNKNOWN";
|
||||
public static final String SD_ED_TYPE_PROFILE_NOTYPE = "SD_ED_TYPE_PROFILE_NOTYPE";
|
||||
public static final String SD_ED_TYPE_PROFILE_WRONG = "SD_ED_TYPE_PROFILE_WRONG";
|
||||
|
|
|
@ -701,4 +701,4 @@ TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG = The value in the instance ({2}) is
|
|||
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM = The value in the instance ({0} {1}) is greater than the specified maxValue ({2} {3}) after UCUM conversion
|
||||
TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_ERROR = Base64 encoded values are not allowed to contain any whitespace (per RFC 4648). Note that non-validating readers are encouraged to accept whitespace anyway
|
||||
TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_WARNING = Base64 encoded values SHOULD not contain any whitespace (per RFC 4648). Note that non-validating readers are encouraged to accept whitespace anyway
|
||||
|
||||
SD_DERIVATION_KIND_MISMATCH = The structure definition constrains a kind of {0}, but has a different kind ({1})
|
||||
|
|
|
@ -304,8 +304,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
} else if (item instanceof Element) {
|
||||
Element e = (Element) item;
|
||||
if (e.getSpecial() != null) {
|
||||
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||
if (e.getSpecial() == SpecialElement.CONTAINED) {
|
||||
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource(), ctxt.getGroupingResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||
} else if (e.getSpecial() != null) {
|
||||
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource(), ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||
} else {
|
||||
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||
}
|
||||
|
@ -1312,7 +1314,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
String system = c.getSystem();
|
||||
String display = c.getDisplay();
|
||||
String version = c.getVersion();
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, system == null || isCodeSystemReferenceValid(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
|
||||
if (system != null && code != null && !noTerminologyChecks) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
|
||||
|
@ -1568,7 +1570,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
private void checkCodedElement(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay, NodeStack stack,
|
||||
String theCode, String theSystem, String theVersion, String theDisplay) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, theSystem == null || isCodeSystemReferenceValid(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, Utilities.noString(theCode) || !Utilities.noString(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_NO_CODE);
|
||||
|
||||
if (theSystem != null && theCode != null && !noTerminologyChecks) {
|
||||
|
@ -2023,7 +2025,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
private void checkIdentifier(List<ValidationMessage> errors, String path, Element element, ElementDefinition context) {
|
||||
String system = element.getNamedChildValue("system");
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM);
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, system == null || isIdentifierSystemReferenceValid(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM);
|
||||
if ("urn:ietf:rfc:3986".equals(system)) {
|
||||
String value = element.getNamedChildValue("value");
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(value), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE);
|
||||
|
@ -2889,7 +2891,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !isSuspiciousReference(ref), I18nConstants.REFERENCE_REF_SUSPICIOUS, ref);
|
||||
|
||||
ResolvedReference we = localResolve(ref, stack, errors, path, hostContext.getRootResource(), element);
|
||||
ResolvedReference we = localResolve(ref, stack, errors, path, hostContext.getRootResource(), hostContext.getGroupingResource(), element);
|
||||
String refType;
|
||||
if (ref.startsWith("#")) {
|
||||
refType = "contained";
|
||||
|
@ -3488,13 +3490,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return fmt.length() > 10 && (fmt.substring(10).contains("-") || fmt.substring(10).contains("+") || fmt.substring(10).contains("Z"));
|
||||
}
|
||||
|
||||
private boolean isAbsolute(String uri) {
|
||||
return Utilities.noString(uri) || uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:uuid:") || uri.startsWith("urn:oid:") || uri.startsWith("urn:ietf:")
|
||||
|| uri.startsWith("urn:iso:") || uri.startsWith("urn:iso-astm:") || uri.startsWith("mailto:")|| isValidFHIRUrn(uri);
|
||||
private boolean isAbsolute(String uri, String... protocols) {
|
||||
return Utilities.noString(uri) || uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:");
|
||||
}
|
||||
|
||||
private boolean isValidFHIRUrn(String uri) {
|
||||
return (uri.equals("urn:x-fhir:uk:id:nhs-number")) || uri.startsWith("urn:"); // Anyone can invent a URN, so why should we complain?
|
||||
private boolean isCodeSystemReferenceValid(String uri) {
|
||||
return isSystemReferenceValid(uri);
|
||||
}
|
||||
|
||||
private boolean isIdentifierSystemReferenceValid(String uri) {
|
||||
return isSystemReferenceValid(uri) || uri.startsWith("ldap:");
|
||||
}
|
||||
|
||||
private boolean isSystemReferenceValid(String uri) {
|
||||
return uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:");
|
||||
}
|
||||
|
||||
public boolean isAnyExtensionsAllowed() {
|
||||
|
@ -3577,7 +3586,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return true;
|
||||
}
|
||||
|
||||
private ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element source) {
|
||||
private ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element groupingResource, Element source) {
|
||||
if (ref.startsWith("#")) {
|
||||
// work back through the parent list.
|
||||
// really, there should only be one level for this (contained resources cannot contain
|
||||
|
@ -3677,11 +3686,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
stack = stack.getParent();
|
||||
}
|
||||
// we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity.
|
||||
if (rootResource != null && BUNDLE.equals(rootResource.fhirType())) {
|
||||
String type = rootResource.getChildValue(TYPE);
|
||||
Element entry = getEntryForSource(rootResource, source);
|
||||
if (groupingResource != null && BUNDLE.equals(groupingResource.fhirType())) { // it could also be a Parameters resource - that case isn't handled yet
|
||||
String type = groupingResource.getChildValue(TYPE);
|
||||
Element entry = getEntryForSource(groupingResource, source);
|
||||
fullUrl = entry.getChildValue(FULL_URL);
|
||||
IndexedElement res = getFromBundle(rootResource, ref, fullUrl, errors, path, type, "transaction".equals(type));
|
||||
IndexedElement res = getFromBundle(groupingResource, ref, fullUrl, errors, path, type, "transaction".equals(type));
|
||||
if (res == null) {
|
||||
return null;
|
||||
} else {
|
||||
|
@ -3758,7 +3767,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
|
||||
private Element resolve(Object appContext, String ref, NodeStack stack, List<ValidationMessage> errors, String path) throws IOException, FHIRException {
|
||||
Element local = localResolve(ref, stack, errors, path, null, null).getFocus();
|
||||
Element local = localResolve(ref, stack, errors, path, null, null, null).getFocus();
|
||||
if (local != null)
|
||||
return local;
|
||||
if (fetcher == null)
|
||||
|
@ -4591,7 +4600,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
ValidatorHostContext hc = null;
|
||||
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
|
||||
resource = element;
|
||||
hc = hostContext.forEntry(element);
|
||||
assert Utilities.existsInList(hostContext.getRootResource().fhirType(), "Bundle", "Parameters");
|
||||
hc = hostContext.forEntry(element, hostContext.getRootResource()); // root becomes the grouping resource (should be either bundle or parameters)
|
||||
} else {
|
||||
hc = hostContext.forContained(element);
|
||||
}
|
||||
|
|
|
@ -97,6 +97,8 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
}
|
||||
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")),
|
||||
I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind"));
|
||||
}
|
||||
} catch (FHIRException | IOException e) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
|
||||
|
|
|
@ -16,6 +16,7 @@ public class ValidatorHostContext {
|
|||
private Element resource;
|
||||
// the resource that is the scope of id resolution - either the same as resource, or the resource the contains that resource. This can only be one level deep.
|
||||
private Element rootResource;
|
||||
private Element groupingResource; // either a bundle or a parameters that holds the rootResource (for reference resolution)
|
||||
|
||||
private StructureDefinition profile; // the profile that contains the content being validated
|
||||
private boolean checkSpecials = true;
|
||||
|
@ -29,7 +30,7 @@ public class ValidatorHostContext {
|
|||
this.appContext = appContext;
|
||||
this.resource = element;
|
||||
this.rootResource = element;
|
||||
// no container
|
||||
// no groupingResource (Bundle or Parameters)
|
||||
dump("creating");
|
||||
}
|
||||
|
||||
|
@ -37,7 +38,15 @@ public class ValidatorHostContext {
|
|||
this.appContext = appContext;
|
||||
this.resource = element;
|
||||
this.rootResource = root;
|
||||
// no container
|
||||
// no groupingResource (Bundle or Parameters)
|
||||
dump("creating");
|
||||
}
|
||||
|
||||
public ValidatorHostContext(Object appContext, Element element, Element root, Element groupingResource) {
|
||||
this.appContext = appContext;
|
||||
this.resource = element;
|
||||
this.rootResource = root;
|
||||
this.groupingResource = groupingResource;
|
||||
dump("creating");
|
||||
}
|
||||
|
||||
|
@ -65,6 +74,10 @@ public class ValidatorHostContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Element getGroupingResource() {
|
||||
return groupingResource;
|
||||
}
|
||||
|
||||
public StructureDefinition getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
@ -106,15 +119,17 @@ public class ValidatorHostContext {
|
|||
res.rootResource = resource;
|
||||
res.resource = element;
|
||||
res.profile = profile;
|
||||
res.groupingResource = groupingResource;
|
||||
res.dump("forContained");
|
||||
return res;
|
||||
}
|
||||
|
||||
public ValidatorHostContext forEntry(Element element) {
|
||||
public ValidatorHostContext forEntry(Element element, Element groupingResource) {
|
||||
ValidatorHostContext res = new ValidatorHostContext(appContext);
|
||||
res.rootResource = element;
|
||||
res.resource = element;
|
||||
res.profile = profile;
|
||||
res.groupingResource = groupingResource;
|
||||
res.dump("forEntry");
|
||||
return res;
|
||||
}
|
||||
|
@ -124,6 +139,7 @@ public class ValidatorHostContext {
|
|||
res.resource = resource;
|
||||
res.rootResource = rootResource;
|
||||
res.profile = profile;
|
||||
res.groupingResource = groupingResource;
|
||||
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
|
||||
res.dump("forProfile "+profile.getUrl());
|
||||
return res;
|
||||
|
@ -134,6 +150,7 @@ public class ValidatorHostContext {
|
|||
res.resource = resource;
|
||||
res.rootResource = resource;
|
||||
res.profile = profile;
|
||||
res.groupingResource = groupingResource;
|
||||
res.checkSpecials = false;
|
||||
res.dump("forLocalReference "+profile.getUrl());
|
||||
return res;
|
||||
|
@ -151,6 +168,7 @@ public class ValidatorHostContext {
|
|||
res.resource = resource;
|
||||
res.rootResource = resource;
|
||||
res.profile = profile;
|
||||
res.groupingResource = null;
|
||||
res.checkSpecials = false;
|
||||
res.dump("forRemoteReference "+profile.getUrl());
|
||||
return res;
|
||||
|
@ -160,6 +178,7 @@ public class ValidatorHostContext {
|
|||
ValidatorHostContext res = new ValidatorHostContext(appContext);
|
||||
res.resource = resource;
|
||||
res.rootResource = resource;
|
||||
res.groupingResource = groupingResource;
|
||||
res.profile = profile;
|
||||
res.checkSpecials = false;
|
||||
res.sliceRecords = new HashMap<String, List<ValidationMessage>>();
|
||||
|
|
Loading…
Reference in New Issue