Validator cleanup (#365)
* cleaning up validator class * wip * I left my debug code in
This commit is contained in:
parent
9bbb78e23d
commit
36fa3a97af
|
@ -67,7 +67,6 @@ public class TimeTracker {
|
|||
c.count++;
|
||||
c.length = c.length + System.nanoTime() - session.start;
|
||||
}
|
||||
|
||||
|
||||
public String report() {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
|
|
|
@ -6,9 +6,7 @@ public class TimeTracker {
|
|||
private long sdTime = 0;
|
||||
private long loadTime = 0;
|
||||
private long fpeTime = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
public long getOverall() {
|
||||
return overall;
|
||||
}
|
||||
|
@ -51,7 +49,5 @@ public class TimeTracker {
|
|||
sdTime = 0;
|
||||
loadTime = 0;
|
||||
fpeTime = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,33 +1,33 @@
|
|||
package org.hl7.fhir.validation;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc
|
||||
|
@ -58,22 +58,16 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.ValidatorGui;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.services.ComparisonService;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
import org.hl7.fhir.validation.cli.utils.Common;
|
||||
import org.hl7.fhir.validation.cli.utils.Display;
|
||||
import org.hl7.fhir.validation.cli.utils.Params;
|
||||
import org.hl7.fhir.validation.cli.utils.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* A executable class that will validate one or more FHIR resources against
|
||||
|
@ -84,125 +78,108 @@ import org.hl7.fhir.validation.cli.utils.Params;
|
|||
* if you want to host validation inside a process, skip this class, and look at
|
||||
* ValidationEngine
|
||||
* <p>
|
||||
* todo: find a gome for this:
|
||||
* todo: find a home for this:
|
||||
*
|
||||
* @author Grahame
|
||||
*/
|
||||
public class Validator {
|
||||
|
||||
public enum EngineMode {
|
||||
VALIDATION, TRANSFORM, NARRATIVE, SNAPSHOT, SCAN, CONVERT, FHIRPATH, VERSION
|
||||
}
|
||||
|
||||
public enum QuestionnaireMode { NONE, CHECK, REQUIRED }
|
||||
|
||||
private static CliContext cliContext;
|
||||
|
||||
private static String getNamedParam(String[] args, String param) {
|
||||
boolean found = false;
|
||||
for (String a : args) {
|
||||
if (found)
|
||||
return a;
|
||||
if (a.equals(param)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String toMB(long maxMemory) {
|
||||
return Long.toString(maxMemory / (1024 * 1024));
|
||||
}
|
||||
|
||||
private static CliContext getCliContext() {
|
||||
if (cliContext == null) {
|
||||
cliContext = new CliContext();
|
||||
}
|
||||
return cliContext;
|
||||
}
|
||||
|
||||
private static void goToWebPage(String url) {
|
||||
try {
|
||||
|
||||
URI uri= new URI(url);
|
||||
|
||||
java.awt.Desktop.getDesktop().browse(uri);
|
||||
System.out.println("Web page opened in browser");
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public static final String HTTP_PROXY_HOST = "http.proxyHost";
|
||||
public static final String HTTP_PROXY_PORT = "http.proxyPort";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
TimeTracker tt = new TimeTracker();
|
||||
TimeTracker.Session tts = tt.start("Loading");
|
||||
TimeTracker.Session tts = tt.start("Loading");
|
||||
|
||||
System.out.println("FHIR Validation tool " + VersionUtil.getVersionString());
|
||||
System.out.println(" Java: " + System.getProperty("java.version") + " from " + System.getProperty("java.home") + " on " + System.getProperty("os.arch") + " (" + System.getProperty("sun.arch.data.model") + "bit). " + toMB(Runtime.getRuntime().maxMemory()) + "MB available");
|
||||
String proxy = getNamedParam(args, Params.PROXY);
|
||||
if (!Utilities.noString(proxy)) {
|
||||
String[] p = proxy.split("\\:");
|
||||
System.setProperty("http.proxyHost", p[0]);
|
||||
System.setProperty("http.proxyPort", p[1]);
|
||||
Display.displayVersion();
|
||||
Display.displaySystemInfo();
|
||||
|
||||
if (Params.hasParam(args, Params.PROXY)) {
|
||||
String[] p = Params.getParam(args, Params.PROXY).split("\\:");
|
||||
System.setProperty(HTTP_PROXY_HOST, p[0]);
|
||||
System.setProperty(HTTP_PROXY_PORT, p[1]);
|
||||
}
|
||||
|
||||
if (Params.hasParam(args, Params.GUI)) {
|
||||
cliContext = Params.loadCliContext(args);
|
||||
String v = Common.getVersion(args);
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validationEngine = Common.getValidationEngine(v, definitions, cliContext.getTxLog(), null);
|
||||
ValidatorGui.start(cliContext, validationEngine, true);
|
||||
} else if (Params.hasParam(args, Params.TEST)) {
|
||||
CliContext cliContext = Params.loadCliContext(args);
|
||||
|
||||
if (Params.hasParam(args, Params.TEST)) {
|
||||
Common.runValidationEngineTests();
|
||||
} else if (args.length == 0 || Params.hasParam(args, Params.HELP) || Params.hasParam(args, "?") || Params.hasParam(args, "-?") || Params.hasParam(args, "/?")) {
|
||||
} else if (shouldDisplayHelpToUser(args)) {
|
||||
Display.displayHelpDetails();
|
||||
} else if (Params.hasParam(args, Params.COMPARE)) {
|
||||
Display.printCliArgumentsAndInfo(args);
|
||||
String dest = Params.getParam(args, Params.DESTINATION);
|
||||
if (dest == null)
|
||||
System.out.println("no -dest parameter provided");
|
||||
else if (!new File(dest).isDirectory())
|
||||
System.out.println("Specified destination (-dest parameter) is not valid: \"" + dest + "\")");
|
||||
else {
|
||||
// first, prepare the context
|
||||
cliContext = Params.loadCliContext(args);
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
String v = VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions, tt);
|
||||
ComparisonService.doLeftRightComparison(args, dest, validator);
|
||||
if (destinationDirectoryValid(Params.getParam(args, Params.DESTINATION))) {
|
||||
doLeftRightComparison(args, cliContext, tt);
|
||||
}
|
||||
} else {
|
||||
Display.printCliArgumentsAndInfo(args);
|
||||
cliContext = Params.loadCliContext(args);
|
||||
doValidation(tt, tts, cliContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
private static boolean destinationDirectoryValid(String dest) {
|
||||
if (dest == null) {
|
||||
System.out.println("no -dest parameter provided");
|
||||
return false;
|
||||
} else if (!new File(dest).isDirectory()) {
|
||||
System.out.println("Specified destination (-dest parameter) is not valid: \"" + dest + "\")");
|
||||
return false;
|
||||
} else {
|
||||
System.out.println("Valid destination directory provided: \"" + dest + "\")");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Loading");
|
||||
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long). Version gets spit out a couple of lines later after we've loaded the context
|
||||
String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions, tt);
|
||||
tts.end();
|
||||
if (cliContext.getMode() == EngineMode.VERSION) {
|
||||
private static boolean shouldDisplayHelpToUser(String[] args) {
|
||||
return (args.length == 0
|
||||
|| Params.hasParam(args, Params.HELP)
|
||||
|| Params.hasParam(args, "?")
|
||||
|| Params.hasParam(args, "-?")
|
||||
|| Params.hasParam(args, "/?"));
|
||||
}
|
||||
|
||||
ValidationService.transformVersion(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.TRANSFORM) {
|
||||
private static void doLeftRightComparison(String[] args, CliContext cliContext, TimeTracker tt) throws Exception {
|
||||
Display.printCliArgumentsAndInfo(args);
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
String v = VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions, tt);
|
||||
ComparisonService.doLeftRightComparison(args, Params.getParam(args, Params.DESTINATION), validator);
|
||||
}
|
||||
|
||||
private static void doValidation(TimeTracker tt, TimeTracker.Session tts, CliContext cliContext) throws Exception {
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
System.out.println("Loading");
|
||||
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long).
|
||||
// Version gets spit out a couple of lines later after we've loaded the context
|
||||
String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions, tt);
|
||||
tts.end();
|
||||
switch (cliContext.getMode()) {
|
||||
case TRANSFORM:
|
||||
ValidationService.transform(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.NARRATIVE) {
|
||||
break;
|
||||
case NARRATIVE:
|
||||
ValidationService.generateNarrative(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.SNAPSHOT) {
|
||||
break;
|
||||
case SNAPSHOT:
|
||||
ValidationService.generateSnapshot(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.CONVERT) {
|
||||
break;
|
||||
case CONVERT:
|
||||
ValidationService.convertSources(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.FHIRPATH) {
|
||||
break;
|
||||
case FHIRPATH:
|
||||
ValidationService.evaluateFhirpath(cliContext, validator);
|
||||
} else {
|
||||
break;
|
||||
case VERSION:
|
||||
ValidationService.transformVersion(cliContext, validator);
|
||||
break;
|
||||
case VALIDATION:
|
||||
case SCAN:
|
||||
default:
|
||||
for (String s : cliContext.getProfiles()) {
|
||||
if (!validator.getContext().hasResource(StructureDefinition.class, s) && !validator.getContext().hasResource(ImplementationGuide.class, s)) {
|
||||
System.out.println(" Fetch Profile from " + s);
|
||||
|
@ -215,10 +192,9 @@ public class Validator {
|
|||
} else {
|
||||
ValidationService.validateSources(cliContext, validator);
|
||||
}
|
||||
}
|
||||
System.out.println("Done. "+tt.report());
|
||||
break;
|
||||
}
|
||||
|
||||
System.out.println("Done. " + tt.report());
|
||||
}
|
||||
|
||||
public static String determineVersion(CliContext cliContext) throws Exception {
|
||||
|
@ -228,17 +204,17 @@ public class Validator {
|
|||
System.out.println("Scanning for versions (no -version parameter):");
|
||||
VersionSourceInformation versions = ValidationService.scanForVersions(cliContext);
|
||||
for (String s : versions.getReport()) {
|
||||
System.out.println(" "+s);
|
||||
System.out.println(" " + s);
|
||||
}
|
||||
if (versions.isEmpty()) {
|
||||
System.out.println("-> Using Default version '"+VersionUtilities.CURRENT_VERSION+"'");
|
||||
System.out.println("-> Using Default version '" + VersionUtilities.CURRENT_VERSION + "'");
|
||||
return "current";
|
||||
}
|
||||
if (versions.size() == 1) {
|
||||
System.out.println("-> use version "+versions.version());
|
||||
return versions.version();
|
||||
System.out.println("-> use version " + versions.version());
|
||||
return versions.version();
|
||||
}
|
||||
throw new Exception("-> Multiple versions found. Specify a particular version using the -version parameter");
|
||||
throw new Exception("-> Multiple versions found. Specify a particular version using the -version parameter");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -8,7 +8,8 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule;
|
||||
import org.hl7.fhir.validation.Validator;
|
||||
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
|
||||
import org.hl7.fhir.validation.cli.utils.EngineMode;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
@ -60,7 +61,7 @@ public class CliContext {
|
|||
@JsonProperty("igs")
|
||||
private List<String> igs = new ArrayList<String>();
|
||||
@JsonProperty("questionnaire")
|
||||
private Validator.QuestionnaireMode questionnaireMode = Validator.QuestionnaireMode.CHECK;
|
||||
private QuestionnaireMode questionnaireMode = QuestionnaireMode.CHECK;
|
||||
|
||||
@JsonProperty("profiles")
|
||||
private List<String> profiles = new ArrayList<String>();
|
||||
|
@ -68,7 +69,7 @@ public class CliContext {
|
|||
private List<String> sources = new ArrayList<String>();
|
||||
|
||||
@JsonProperty("mode")
|
||||
private Validator.EngineMode mode = Validator.EngineMode.VALIDATION;
|
||||
private EngineMode mode = EngineMode.VALIDATION;
|
||||
|
||||
@JsonProperty("securityChecks")
|
||||
private boolean securityChecks = false;
|
||||
|
@ -125,12 +126,12 @@ public class CliContext {
|
|||
}
|
||||
|
||||
@JsonProperty("questionnaire")
|
||||
public Validator.QuestionnaireMode getQuestionnaireMode() {
|
||||
public QuestionnaireMode getQuestionnaireMode() {
|
||||
return questionnaireMode;
|
||||
}
|
||||
|
||||
@JsonProperty("questionnaire")
|
||||
public CliContext setQuestionnaireMode(Validator.QuestionnaireMode questionnaireMode) {
|
||||
public CliContext setQuestionnaireMode(QuestionnaireMode questionnaireMode) {
|
||||
this.questionnaireMode = questionnaireMode;
|
||||
return this;
|
||||
}
|
||||
|
@ -230,12 +231,12 @@ public class CliContext {
|
|||
}
|
||||
|
||||
@JsonProperty("mode")
|
||||
public Validator.EngineMode getMode() {
|
||||
public EngineMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
@JsonProperty("mode")
|
||||
public CliContext setMode(Validator.EngineMode mode) {
|
||||
public CliContext setMode(EngineMode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
@ -494,4 +495,40 @@ public class CliContext {
|
|||
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, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CliContext{" +
|
||||
"doNative=" + doNative +
|
||||
", anyExtensionsAllowed=" + anyExtensionsAllowed +
|
||||
", hintAboutNonMustSupport=" + hintAboutNonMustSupport +
|
||||
", recursive=" + recursive +
|
||||
", doDebug=" + doDebug +
|
||||
", assumeValidRestReferences=" + assumeValidRestReferences +
|
||||
", canDoNative=" + canDoNative +
|
||||
", noInternalCaching=" + noInternalCaching +
|
||||
", noExtensibleBindingMessages=" + noExtensibleBindingMessages +
|
||||
", map='" + map + '\'' +
|
||||
", output='" + output + '\'' +
|
||||
", txServer='" + txServer + '\'' +
|
||||
", sv='" + sv + '\'' +
|
||||
", txLog='" + txLog + '\'' +
|
||||
", mapLog='" + mapLog + '\'' +
|
||||
", lang='" + lang + '\'' +
|
||||
", fhirpath='" + fhirpath + '\'' +
|
||||
", snomedCT='" + snomedCT + '\'' +
|
||||
", targetVer='" + targetVer + '\'' +
|
||||
", igs=" + igs +
|
||||
", questionnaireMode=" + questionnaireMode +
|
||||
", profiles=" + profiles +
|
||||
", sources=" + sources +
|
||||
", mode=" + mode +
|
||||
", securityChecks=" + securityChecks +
|
||||
", crumbTrails=" + crumbTrails +
|
||||
", showTimes=" + showTimes +
|
||||
", locale='" + locale + '\'' +
|
||||
", locations=" + locations +
|
||||
", bundleValidationRules=" + bundleValidationRules +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
|
||||
public class ScanOutputItem {
|
||||
private String ref;
|
||||
private ImplementationGuide ig;
|
||||
private StructureDefinition profile;
|
||||
private OperationOutcome outcome;
|
||||
private String id;
|
||||
|
||||
public ScanOutputItem(String ref, ImplementationGuide ig, StructureDefinition profile, OperationOutcome outcome) {
|
||||
super();
|
||||
this.ref = ref;
|
||||
this.ig = ig;
|
||||
this.profile = profile;
|
||||
this.outcome = outcome;
|
||||
}
|
||||
|
||||
public String getRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
public ImplementationGuide getIg() {
|
||||
return ig;
|
||||
}
|
||||
|
||||
public StructureDefinition getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
public OperationOutcome getOutcome() {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
if (profile != null)
|
||||
return "Validate " + ref + " against " + profile.present() + " (" + profile.getUrl() + ")";
|
||||
if (ig != null)
|
||||
return "Validate " + ref + " against global profile specified in " + ig.present() + " (" + ig.getUrl() + ")";
|
||||
return "Validate " + ref + " against FHIR Spec";
|
||||
}
|
||||
}
|
|
@ -26,12 +26,8 @@ import org.hl7.fhir.utilities.TimeTracker;
|
|||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.model.FileInfo;
|
||||
import org.hl7.fhir.validation.cli.model.ValidationOutcome;
|
||||
import org.hl7.fhir.validation.cli.model.ValidationRequest;
|
||||
import org.hl7.fhir.validation.cli.model.ValidationResponse;
|
||||
import org.hl7.fhir.validation.cli.model.*;
|
||||
import org.hl7.fhir.validation.cli.utils.VersionSourceInformation;
|
||||
|
||||
public class ValidationService {
|
||||
|
||||
|
@ -110,7 +106,7 @@ public class ValidationService {
|
|||
if (ig.getUrl().contains("/ImplementationGuide") && !ig.getUrl().equals("http://hl7.org/fhir/ImplementationGuide/fhir"))
|
||||
urls.add(ig.getUrl());
|
||||
}
|
||||
List<ValidationEngine.ScanOutputItem> res = validator.validateScan(cliContext.getSources(), urls);
|
||||
List<ScanOutputItem> res = validator.validateScan(cliContext.getSources(), urls);
|
||||
validator.genScanOutput(cliContext.getOutput(), res);
|
||||
System.out.println("Done. output in " + Utilities.path(cliContext.getOutput(), "scan.html"));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
public class AsteriskFilter implements FilenameFilter {
|
||||
String dir;
|
||||
String regex;
|
||||
|
||||
public AsteriskFilter(String filter) throws IOException {
|
||||
if (!filter.matches("(.*(\\\\|\\/))*(.*)\\*(.*)"))
|
||||
throw new IOException("Filter names must have the following syntax: [directorypath][prefix]?*[suffix]? I.e. The asterisk must be in the filename, not the directory path");
|
||||
dir = filter.replaceAll("(.*(\\\\|\\/))*(.*)\\*(.*)", "$1");
|
||||
String expression = filter.replaceAll("(.*(\\\\|\\/))*(.*)", "$3");
|
||||
regex = "";
|
||||
for (int i = 0; i < expression.length(); i++) {
|
||||
if (Character.isAlphabetic(expression.codePointAt(i)) || Character.isDigit(expression.codePointAt(i)))
|
||||
regex = regex + expression.charAt(i);
|
||||
else if (expression.charAt(i)=='*')
|
||||
regex = regex + ".*";
|
||||
else
|
||||
regex = regex + "\\" + expression.charAt(i);
|
||||
}
|
||||
File f = new File(dir);
|
||||
if (!f.exists()) {
|
||||
throw new IOException("Directory " + dir + " does not exist");
|
||||
}
|
||||
if (!f.isDirectory()) {
|
||||
throw new IOException("Directory " + dir + " is not a directory");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean accept(File dir, String s) {
|
||||
return s.matches(regex);
|
||||
}
|
||||
|
||||
public String getDir() {
|
||||
return dir;
|
||||
}
|
||||
}
|
|
@ -92,4 +92,12 @@ public class Common {
|
|||
return ve;
|
||||
}
|
||||
|
||||
public static boolean isNetworkPath(String path) {
|
||||
return path.startsWith("https:") || path.startsWith("http:");
|
||||
}
|
||||
|
||||
public static boolean isWildcardPath(String name) {
|
||||
return name.contains("*");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.r5.model.Constants;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.ToolsVersion;
|
||||
import org.hl7.fhir.validation.VersionUtil;
|
||||
|
||||
/**
|
||||
* Class for displaying output to the cli user.
|
||||
|
@ -14,6 +18,10 @@ import org.hl7.fhir.utilities.npm.ToolsVersion;
|
|||
*/
|
||||
public class Display {
|
||||
|
||||
private static String toMB(long maxMemory) {
|
||||
return Long.toString(maxMemory / (1024 * 1024));
|
||||
}
|
||||
|
||||
public static void printCliArgumentsAndInfo(String[] args) throws IOException {
|
||||
System.out.println(" Paths: Current = " + System.getProperty("user.dir") + ", Package Cache = " + new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION).getFolder());
|
||||
System.out.print(" Params:");
|
||||
|
@ -23,128 +31,35 @@ public class Display {
|
|||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the help details from resources/help.txt, and displays them on the command line to the user.
|
||||
*/
|
||||
public static void displayHelpDetails() {
|
||||
System.out.println("");
|
||||
System.out.println("The FHIR validation tool validates a FHIR resource or bundle.");
|
||||
System.out.println("The validation tool compares a resource against the base definitions and any");
|
||||
System.out.println("profiles declared in the resource (Resource.meta.profile) or specified on the ");
|
||||
System.out.println("command line");
|
||||
System.out.println("");
|
||||
System.out.println("The FHIR validation tool validates a FHIR resource or bundle.");
|
||||
System.out.println("Schema and schematron checking is performed, then some additional checks are performed. ");
|
||||
System.out.println("* XML & Json (FHIR versions 1.0, 1.4, 3.0, 4.0, " + Constants.VERSION_MM + ")");
|
||||
System.out.println("* Turtle (FHIR versions 3.0, 4.0, " + Constants.VERSION_MM + ")");
|
||||
System.out.println("");
|
||||
System.out.println("If requested, instances will also be verified against the appropriate schema");
|
||||
System.out.println("W3C XML Schema, JSON schema or ShEx, as appropriate");
|
||||
System.out.println("");
|
||||
System.out.println("Usage: java -jar [validator].jar (parameters)");
|
||||
System.out.println("");
|
||||
System.out.println("The following parameters are supported:");
|
||||
System.out.println("[source]: a file, url, directory or pattern for resources to validate. At");
|
||||
System.out.println(" least one source must be declared. If there is more than one source or if");
|
||||
System.out.println(" the source is other than a single file or url and the output parameter is");
|
||||
System.out.println(" used, results will be provided as a Bundle.");
|
||||
System.out.println(" Patterns are limited to a directory followed by a filename with an embedded");
|
||||
System.out.println(" asterisk. E.g. foo*-examples.xml or someresource.*, etc.");
|
||||
System.out.println("-version [ver]: The FHIR version to use. This can only appear once. ");
|
||||
System.out.println(" valid values 1.0 | 1.4 | 3.0 | " + VersionUtilities.CURRENT_VERSION + " or 1.0.2 | 1.4.0 | 3.0.2 | 4.0.1 | " + VersionUtilities.CURRENT_FULL_VERSION);
|
||||
System.out.println(" Default value is " + VersionUtilities.CURRENT_VERSION);
|
||||
System.out.println("-ig [package|file|folder|url]: an IG or profile definition to load. Can be ");
|
||||
System.out.println(" the URL of an implementation guide or a package ([id]-[ver]) for");
|
||||
System.out.println(" a built implementation guide or a local folder that contains a");
|
||||
System.out.println(" set of conformance resources.");
|
||||
System.out.println(" No default value. This parameter can appear any number of times");
|
||||
System.out.println("-tx [url]: the [base] url of a FHIR terminology service");
|
||||
System.out.println(" Default value is http://tx.fhir.org. This parameter can appear once");
|
||||
System.out.println(" To run without terminology value, specific n/a as the URL");
|
||||
System.out.println("-txLog [file]: Produce a log of the terminology server operations in [file]");
|
||||
System.out.println(" Default value is not to produce a log");
|
||||
System.out.println("-profile [url]: the canonical URL to validate against (same as if it was ");
|
||||
System.out.println(" specified in Resource.meta.profile). If no profile is specified, the ");
|
||||
System.out.println(" resource is validated against the base specification. This parameter ");
|
||||
System.out.println(" can appear any number of times.");
|
||||
System.out.println(" Note: the profile (and it's dependencies) have to be made available ");
|
||||
System.out.println(" through one of the -ig parameters. Note that package dependencies will ");
|
||||
System.out.println(" automatically be resolved");
|
||||
System.out.println("-questionnaire [file|url}: the location of a questionnaire. If provided, then the validator will validate");
|
||||
System.out.println(" any QuestionnaireResponse that claims to match the Questionnaire against it");
|
||||
System.out.println(" no default value. This parameter can appear any number of times");
|
||||
System.out.println("-output [file]: a filename for the results (OperationOutcome)");
|
||||
System.out.println(" Default: results are sent to the std out.");
|
||||
System.out.println("-debug");
|
||||
System.out.println(" Produce additional information about the loading/validation process");
|
||||
System.out.println("-recurse");
|
||||
System.out.println(" Look in subfolders when -ig refers to a folder");
|
||||
System.out.println("-locale");
|
||||
System.out.println(" Specifies the locale/language of the validation result messages (eg.: de-DE");
|
||||
System.out.println("-sct");
|
||||
System.out.println(" Specify the edition of SNOMED CT to use. Valid Choices:");
|
||||
System.out.println(" intl | us | uk | au | nl | ca | se | dk | es");
|
||||
System.out.println(" tx.fhir.org only supports a subset. To add to this list or tx.fhir.org");
|
||||
System.out.println(" ask on https://chat.fhir.org/#narrow/stream/179202-terminology");
|
||||
System.out.println("-native: use schema for validation as well");
|
||||
System.out.println(" * XML: w3c schema+schematron");
|
||||
System.out.println(" * JSON: json.schema");
|
||||
System.out.println(" * RDF: SHEX");
|
||||
System.out.println(" Default: false");
|
||||
System.out.println("-language: [lang]");
|
||||
System.out.println(" The language to use when validating coding displays - same value as for xml:lang");
|
||||
System.out.println(" Not used if the resource specifies language");
|
||||
System.out.println(" Default: no specified language");
|
||||
System.out.println("-strictExtensions: If present, treat extensions not defined within the specified FHIR version and any");
|
||||
System.out.println(" referenced implementation guides or profiles as errors. (Default is to only raise information messages.)");
|
||||
System.out.println("-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not");
|
||||
System.out.println(" marked as mustSupport=true. Useful to identify elements included that may be ignored by recipients");
|
||||
System.out.println("-assumeValidRestReferences: If present, assume that URLs that reference resources follow the RESTful URI pattern");
|
||||
System.out.println(" and it is safe to infer the type from the URL");
|
||||
System.out.println("-security-checks: If present, check that string content doesn't include any html-like tags that might create");
|
||||
System.out.println(" problems downstream (though all external input must always be santized by escaping for either html or sql)");
|
||||
System.out.println("");
|
||||
System.out.println("The validator also supports the param -proxy=[address]:[port] for if you use a proxy");
|
||||
System.out.println("");
|
||||
System.out.println("Parameters can appear in any order");
|
||||
System.out.println("");
|
||||
System.out.println("Alternatively, you can use the validator to execute a transformation as described by a structure map.");
|
||||
System.out.println("To do this, you must provide some additional parameters:");
|
||||
System.out.println("");
|
||||
System.out.println(" -transform [map]");
|
||||
System.out.println("");
|
||||
System.out.println("* [map] the URI of the map that the transform starts with");
|
||||
System.out.println("");
|
||||
System.out.println("Any other dependency maps have to be loaded through an -ig reference ");
|
||||
System.out.println("");
|
||||
System.out.println("-transform uses the parameters -defn, -txserver, -ig (at least one with the map files), and -output");
|
||||
System.out.println("");
|
||||
System.out.println("Alternatively, you can use the validator to generate narrative for a resource.");
|
||||
System.out.println("To do this, you must provide a specific parameter:");
|
||||
System.out.println("");
|
||||
System.out.println(" -narrative");
|
||||
System.out.println("");
|
||||
System.out.println("-narrative requires the parameters -defn, -txserver, -source, and -output. ig and profile may be used");
|
||||
System.out.println("");
|
||||
System.out.println("Alternatively, you can use the validator to convert a resource or logical model.");
|
||||
System.out.println("To do this, you must provide a specific parameter:");
|
||||
System.out.println("");
|
||||
System.out.println(" -convert");
|
||||
System.out.println("");
|
||||
System.out.println("-convert requires the parameters -source and -output. ig may be used to provide a logical model");
|
||||
System.out.println("");
|
||||
System.out.println("Alternatively, you can use the validator to evaluate a FHIRPath expression on a resource or logical model.");
|
||||
System.out.println("To do this, you must provide a specific parameter:");
|
||||
System.out.println("");
|
||||
System.out.println(" -fhirpath [FHIRPath]");
|
||||
System.out.println("");
|
||||
System.out.println("* [FHIRPath] the FHIRPath expression to evaluate");
|
||||
System.out.println("");
|
||||
System.out.println("-fhirpath requires the parameters -source. ig may be used to provide a logical model");
|
||||
System.out.println("");
|
||||
System.out.println("Finally, you can use the validator to generate a snapshot for a profile.");
|
||||
System.out.println("To do this, you must provide a specific parameter:");
|
||||
System.out.println("");
|
||||
System.out.println(" -snapshot");
|
||||
System.out.println("");
|
||||
System.out.println("-snapshot requires the parameters -defn, -txserver, -source, and -output. ig may be used to provide necessary base profiles");
|
||||
ClassLoader classLoader = Display.class.getClassLoader();
|
||||
File file = new File(classLoader.getResource("help.txt").getFile());
|
||||
try {
|
||||
String data = FileUtils.readFileToString(file, "UTF-8");
|
||||
System.out.println(data);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out system info to the command line.
|
||||
*/
|
||||
public static void displaySystemInfo() {
|
||||
System.out.println(" Java: " + System.getProperty("java.version")
|
||||
+ " from " + System.getProperty("java.home")
|
||||
+ " on " + System.getProperty("os.arch")
|
||||
+ " (" + System.getProperty("sun.arch.data.model") + "bit). "
|
||||
+ toMB(Runtime.getRuntime().maxMemory()) + "MB available");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints current version of the validator.
|
||||
*/
|
||||
public static void displayVersion() {
|
||||
System.out.println("FHIR Validation tool " + VersionUtil.getVersionString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
public enum EngineMode {
|
||||
VALIDATION, TRANSFORM, NARRATIVE, SNAPSHOT, SCAN, CONVERT, FHIRPATH, VERSION
|
||||
}
|
|
@ -6,12 +6,10 @@ import java.util.Locale;
|
|||
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.Validator;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
|
||||
public class Params {
|
||||
|
||||
public static final String GUI = "-gui";
|
||||
public static final String VERSION = "-version";
|
||||
public static final String OUTPUT = "-output";
|
||||
public static final String PROXY = "-proxy";
|
||||
|
@ -74,9 +72,9 @@ public class Params {
|
|||
* @return {@link String} value for the provided param.
|
||||
*/
|
||||
public static String getParam(String[] args, String param) {
|
||||
for (int i = 0; i < args.length - 1; i++)
|
||||
if (args[i].equals(param))
|
||||
return args[i + 1];
|
||||
for (int i = 0; i < args.length - 1; i++) {
|
||||
if (args[i].equals(param)) return args[i + 1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -104,7 +102,7 @@ public class Params {
|
|||
} else {
|
||||
p = args[++i];
|
||||
cliContext.addProfile(p);
|
||||
}
|
||||
}
|
||||
} else if (args[i].equals(BUNDLE)) {
|
||||
String p = null;
|
||||
String r = null;
|
||||
|
@ -124,7 +122,7 @@ public class Params {
|
|||
throw new Error("Specified -questionnaire without indicating questionnaire file");
|
||||
else {
|
||||
String q = args[++i];
|
||||
cliContext.setQuestionnaireMode(Validator.QuestionnaireMode.valueOf(q));
|
||||
cliContext.setQuestionnaireMode(QuestionnaireMode.valueOf(q));
|
||||
}
|
||||
} else if (args[i].equals(NATIVE)) {
|
||||
cliContext.setDoNative(true);
|
||||
|
@ -145,25 +143,25 @@ public class Params {
|
|||
} else if (args[i].equals(STRICT_EXTENSIONS)) {
|
||||
cliContext.setAnyExtensionsAllowed(false);
|
||||
} else if (args[i].equals(NO_INTERNAL_CACHING)) {
|
||||
cliContext.setNoInternalCaching(true);
|
||||
cliContext.setNoInternalCaching(true);
|
||||
} else if (args[i].equals(NO_EXTENSIBLE_BINDING_WARNINGS)) {
|
||||
cliContext.setNoExtensibleBindingMessages(true);
|
||||
cliContext.setNoExtensibleBindingMessages(true);
|
||||
} else if (args[i].equals(HINT_ABOUT_NON_MUST_SUPPORT)) {
|
||||
cliContext.setHintAboutNonMustSupport(true);
|
||||
} else if (args[i].equals(TO_VERSION)) {
|
||||
cliContext.setTargetVer(args[++i]);
|
||||
cliContext.setMode(Validator.EngineMode.VERSION);
|
||||
cliContext.setMode(EngineMode.VERSION);
|
||||
} else if (args[i].equals(DO_NATIVE)) {
|
||||
cliContext.setCanDoNative(true);
|
||||
} else if (args[i].equals(NO_NATIVE)) {
|
||||
cliContext.setCanDoNative(false);
|
||||
} else if (args[i].equals(TRANSFORM)) {
|
||||
cliContext.setMap(args[++i]);
|
||||
cliContext.setMode(Validator.EngineMode.TRANSFORM);
|
||||
cliContext.setMode(EngineMode.TRANSFORM);
|
||||
} else if (args[i].equals(NARRATIVE)) {
|
||||
cliContext.setMode(Validator.EngineMode.NARRATIVE);
|
||||
cliContext.setMode(EngineMode.NARRATIVE);
|
||||
} else if (args[i].equals(SNAPSHOT)) {
|
||||
cliContext.setMode(Validator.EngineMode.SNAPSHOT);
|
||||
cliContext.setMode(EngineMode.SNAPSHOT);
|
||||
} else if (args[i].equals(SECURITY_CHECKS)) {
|
||||
cliContext.setSecurityChecks(true);
|
||||
} else if (args[i].equals(CRUMB_TRAIL)) {
|
||||
|
@ -171,7 +169,7 @@ public class Params {
|
|||
} else if (args[i].equals(SHOW_TIMES)) {
|
||||
cliContext.setShowTimes(true);
|
||||
} else if (args[i].equals(SCAN)) {
|
||||
cliContext.setMode(Validator.EngineMode.SCAN);
|
||||
cliContext.setMode(EngineMode.SCAN);
|
||||
} else if (args[i].equals(TERMINOLOGY)) {
|
||||
if (i + 1 == args.length)
|
||||
throw new Error("Specified -tx without indicating terminology server");
|
||||
|
@ -216,9 +214,9 @@ public class Params {
|
|||
} else if (args[i].startsWith(X)) {
|
||||
i++;
|
||||
} else if (args[i].equals(CONVERT)) {
|
||||
cliContext.setMode(Validator.EngineMode.CONVERT);
|
||||
cliContext.setMode(EngineMode.CONVERT);
|
||||
} else if (args[i].equals(FHIRPATH)) {
|
||||
cliContext.setMode(Validator.EngineMode.FHIRPATH);
|
||||
cliContext.setMode(EngineMode.FHIRPATH);
|
||||
if (cliContext.getFhirpath() == null)
|
||||
if (i + 1 == args.length)
|
||||
throw new Error("Specified -fhirpath without indicating a FHIRPath expression");
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
public enum QuestionnaireMode { NONE, CHECK, REQUIRED }
|
|
@ -0,0 +1,41 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class VersionSourceInformation {
|
||||
|
||||
private List<String> report = new ArrayList<>();
|
||||
private List<String> versions = new ArrayList<>();
|
||||
|
||||
public void see(String version, String src) {
|
||||
version = VersionUtilities.getMajMin(version);
|
||||
report.add(src+": "+version);
|
||||
if (!versions.contains(version)) {
|
||||
versions.add(version);
|
||||
Collections.sort(versions);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return versions.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return versions.size();
|
||||
}
|
||||
|
||||
public String version() {
|
||||
return versions.get(0);
|
||||
}
|
||||
|
||||
public List<String> getReport() {
|
||||
if (report.isEmpty()) {
|
||||
report.add("(nothing found)");
|
||||
}
|
||||
return report;
|
||||
}
|
||||
}
|
|
@ -147,7 +147,7 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.Validator.QuestionnaireMode;
|
||||
import org.hl7.fhir.validation.cli.utils.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;
|
||||
|
|
|
@ -43,8 +43,8 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
|
||||
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;
|
||||
|
@ -86,7 +86,6 @@ public class QuestionnaireValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void validateQuestionnaireElement(List<ValidationMessage> errors, NodeStack ns, Element questionnaire, Element item, List<Element> parents) {
|
||||
// R4+
|
||||
if ((FHIRVersion.isR4Plus(context.getVersion())) && (item.hasChildren("enableWhen"))) {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
|
||||
The FHIR validation tool validates a FHIR resource or bundle.
|
||||
The validation tool compares a resource against the base definitions and any
|
||||
profiles declared in the resource (Resource.meta.profile) or specified on the
|
||||
command line
|
||||
|
||||
The FHIR validation tool validates a FHIR resource or bundle.
|
||||
Schema and schematron checking is performed, then some additional checks are performed.
|
||||
* XML & Json (FHIR versions 1.0, 1.4, 3.0, 4.0, " + Constants.VERSION_MM + ")
|
||||
* Turtle (FHIR versions 3.0, 4.0, " + Constants.VERSION_MM + ")
|
||||
|
||||
If requested, instances will also be verified against the appropriate schema
|
||||
W3C XML Schema, JSON schema or ShEx, as appropriate
|
||||
|
||||
Usage: java -jar [validator].jar (parameters)
|
||||
|
||||
The following parameters are supported:
|
||||
[source]: a file, url, directory or pattern for resources to validate. At
|
||||
least one source must be declared. If there is more than one source or if
|
||||
the source is other than a single file or url and the output parameter is
|
||||
used, results will be provided as a Bundle.
|
||||
Patterns are limited to a directory followed by a filename with an embedded
|
||||
asterisk. E.g. foo*-examples.xml or someresource.*, etc.
|
||||
-version [ver]: The FHIR version to use. This can only appear once.
|
||||
valid values 1.0 | 1.4 | 3.0 | " + VersionUtilities.CURRENT_VERSION + " or 1.0.2 | 1.4.0 | 3.0.2 | 4.0.1 | " + VersionUtilities.CURRENT_FULL_VERSION);
|
||||
Default value is " + VersionUtilities.CURRENT_VERSION);
|
||||
-ig [package|file|folder|url]: an IG or profile definition to load. Can be
|
||||
the URL of an implementation guide or a package ([id]-[ver]) for
|
||||
a built implementation guide or a local folder that contains a
|
||||
set of conformance resources.
|
||||
No default value. This parameter can appear any number of times
|
||||
-tx [url]: the [base] url of a FHIR terminology service
|
||||
Default value is http://tx.fhir.org. This parameter can appear once
|
||||
To run without terminology value, specific n/a as the URL
|
||||
-txLog [file]: Produce a log of the terminology server operations in [file]
|
||||
Default value is not to produce a log
|
||||
-profile [url]: the canonical URL to validate against (same as if it was
|
||||
specified in Resource.meta.profile). If no profile is specified, the
|
||||
resource is validated against the base specification. This parameter
|
||||
can appear any number of times.
|
||||
Note: the profile (and it's dependencies) have to be made available
|
||||
through one of the -ig parameters. Note that package dependencies will
|
||||
automatically be resolved
|
||||
-questionnaire [file|url}: the location of a questionnaire. If provided, then the validator will validate
|
||||
any QuestionnaireResponse that claims to match the Questionnaire against it
|
||||
no default value. This parameter can appear any number of times
|
||||
-output [file]: a filename for the results (OperationOutcome)
|
||||
Default: results are sent to the std out.
|
||||
-debug
|
||||
Produce additional information about the loading/validation process
|
||||
-recurse
|
||||
Look in subfolders when -ig refers to a folder
|
||||
-locale
|
||||
Specifies the locale/language of the validation result messages (eg.: de-DE
|
||||
-sct
|
||||
Specify the edition of SNOMED CT to use. Valid Choices:
|
||||
intl | us | uk | au | nl | ca | se | dk | es
|
||||
tx.fhir.org only supports a subset. To add to this list or tx.fhir.org
|
||||
ask on https://chat.fhir.org/#narrow/stream/179202-terminology
|
||||
-native: use schema for validation as well
|
||||
* XML: w3c schema+schematron
|
||||
* JSON: json.schema
|
||||
* RDF: SHEX
|
||||
Default: false
|
||||
-language: [lang]
|
||||
The language to use when validating coding displays - same value as for xml:lang
|
||||
Not used if the resource specifies language
|
||||
Default: no specified language
|
||||
-strictExtensions: If present, treat extensions not defined within the specified FHIR version and any
|
||||
referenced implementation guides or profiles as errors. (Default is to only raise information messages.)
|
||||
-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not
|
||||
marked as mustSupport=true. Useful to identify elements included that may be ignored by recipients
|
||||
-assumeValidRestReferences: If present, assume that URLs that reference resources follow the RESTful URI pattern
|
||||
and it is safe to infer the type from the URL
|
||||
-security-checks: If present, check that string content doesn't include any html-like tags that might create
|
||||
problems downstream (though all external input must always be santized by escaping for either html or sql)
|
||||
|
||||
The validator also supports the param -proxy=[address]:[port] for if you use a proxy
|
||||
|
||||
Parameters can appear in any order
|
||||
|
||||
Alternatively, you can use the validator to execute a transformation as described by a structure map.
|
||||
To do this, you must provide some additional parameters:
|
||||
|
||||
-transform [map]
|
||||
|
||||
* [map] the URI of the map that the transform starts with
|
||||
|
||||
Any other dependency maps have to be loaded through an -ig reference
|
||||
|
||||
-transform uses the parameters -defn, -txserver, -ig (at least one with the map files), and -output
|
||||
|
||||
Alternatively, you can use the validator to generate narrative for a resource.
|
||||
To do this, you must provide a specific parameter:
|
||||
|
||||
-narrative
|
||||
|
||||
-narrative requires the parameters -defn, -txserver, -source, and -output. ig and profile may be used
|
||||
|
||||
Alternatively, you can use the validator to convert a resource or logical model.
|
||||
To do this, you must provide a specific parameter:
|
||||
|
||||
-convert
|
||||
|
||||
-convert requires the parameters -source and -output. ig may be used to provide a logical model
|
||||
|
||||
Alternatively, you can use the validator to evaluate a FHIRPath expression on a resource or logical model.
|
||||
To do this, you must provide a specific parameter:
|
||||
|
||||
-fhirpath [FHIRPath]
|
||||
|
||||
* [FHIRPath] the FHIRPath expression to evaluate
|
||||
|
||||
-fhirpath requires the parameters -source. ig may be used to provide a logical model
|
||||
|
||||
Finally, you can use the validator to generate a snapshot for a profile.
|
||||
To do this, you must provide a specific parameter:
|
||||
|
||||
-snapshot
|
||||
|
||||
-snapshot requires the parameters -defn, -txserver, -source, and -output. ig may be used to provide necessary base profiles
|
|
@ -1,37 +0,0 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public abstract class BaseRestTest {
|
||||
|
||||
protected final String JSON_MIME_TYPE = "application/json";
|
||||
|
||||
@BeforeAll
|
||||
public static void startServer() {
|
||||
ValidatorGui.start(new CliContext(), null, false);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopServer() {
|
||||
ValidatorGui.stop();
|
||||
}
|
||||
|
||||
public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz)
|
||||
throws IOException {
|
||||
|
||||
String jsonFromResponse = EntityUtils.toString(response.getEntity());
|
||||
ObjectMapper mapper = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
return mapper.readValue(jsonFromResponse, clazz);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.chrome.ChromeOptions;
|
||||
|
||||
import io.github.bonigarcia.wdm.WebDriverManager;
|
||||
|
||||
class ValidatorGuiTest {
|
||||
|
||||
private static final String DEF_TX = "http://tx.fhir.org";
|
||||
private final String HTML_TITLE_TAG = "<title>FHIR HL7 Resrouce Validator GUI</title>";
|
||||
|
||||
@Test
|
||||
@DisplayName("Page boots correctly, and displays index.html")
|
||||
public void UI_contains_correct_heading() throws IOException {
|
||||
ValidatorGui.start(new CliContext(), null, false);
|
||||
WebDriverManager.chromedriver().setup();
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
options.addArguments("--headless");
|
||||
options.addArguments("--disable-gpu");
|
||||
WebDriver driver = new ChromeDriver(options);
|
||||
driver.get("http://localhost:" + ValidatorGui.getPort() + "/home");
|
||||
|
||||
Assertions.assertTrue(driver.getPageSource().contains(HTML_TITLE_TAG));
|
||||
driver.quit();
|
||||
ValidatorGui.stop();
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package org.hl7.fhir.validation.cli.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.hl7.fhir.validation.cli.BaseRestTest;
|
||||
import org.hl7.fhir.validation.cli.ValidatorGui;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class HttpGetContextTest extends BaseRestTest {
|
||||
|
||||
private final String GET_CONTEXT_URL = "http://localhost:" + ValidatorGui.getPort() + "/context";
|
||||
|
||||
@Test
|
||||
@DisplayName("Testing status code on get context endpoint.")
|
||||
public void testStatus() throws IOException {
|
||||
HttpUriRequest request = new HttpGet(GET_CONTEXT_URL);
|
||||
HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
|
||||
Assertions.assertEquals(httpResponse.getStatusLine().getStatusCode(), HttpStatus.SC_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Testing media type on get context endpoint.")
|
||||
public void testMediaType() throws IOException {
|
||||
HttpUriRequest request = new HttpGet(GET_CONTEXT_URL);
|
||||
HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
|
||||
String mimeType = ContentType.getOrDefault(httpResponse.getEntity()).getMimeType();
|
||||
Assertions.assertEquals(JSON_MIME_TYPE, mimeType );
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Testing status code on get context endpoint.")
|
||||
public void testJSONPayload() throws IOException {
|
||||
HttpUriRequest request = new HttpGet(GET_CONTEXT_URL);
|
||||
HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
|
||||
CliContext resource = retrieveResourceFromResponse(httpResponse, CliContext.class);
|
||||
Assertions.assertEquals(new CliContext(), resource);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.validation.cli.controller;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.javalin.http.Context;
|
||||
|
||||
class HttpPutContextTest {
|
||||
|
||||
public CliContextController myCliContextController;
|
||||
|
||||
public HttpPutContextTest() {
|
||||
this.myCliContextController = new CliContextController(null);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
void handleSetCurrentCliContext() {
|
||||
Context context = mock(Context.class);
|
||||
this.myCliContextController.handleSetCurrentCliContext(context);
|
||||
verify(context).status(200);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue