diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java index af381bcd6..bc4241fde 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Validator.java @@ -48,46 +48,12 @@ POSSIBILITY OF SUCH DAMAGE. */ -import java.awt.Desktop; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import org.hl7.fhir.r5.conformance.CapabilityStatementUtilities; -import org.hl7.fhir.r5.conformance.CapabilityStatementUtilities.CapabilityStatementComparisonOutput; -import org.hl7.fhir.r5.conformance.ProfileComparer; -import org.hl7.fhir.r5.context.SimpleWorkerContext; -import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; -import org.hl7.fhir.r5.formats.IParser; -import org.hl7.fhir.r5.formats.IParser.OutputStyle; -import org.hl7.fhir.r5.formats.XmlParser; -import org.hl7.fhir.r5.formats.JsonParser; -import org.hl7.fhir.r5.model.Bundle; -import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; -import org.hl7.fhir.r5.model.CapabilityStatement; -import org.hl7.fhir.r5.model.DomainResource; -import org.hl7.fhir.r5.model.FhirPublication; import org.hl7.fhir.r5.model.ImplementationGuide; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.OperationOutcome; -import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; -import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.utils.KeyGenerator; -import org.hl7.fhir.r5.utils.ToolingExtensions; -import org.hl7.fhir.validation.ValidationEngine.ScanOutputItem; -import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; -import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.validation.cliutils.*; /** @@ -128,365 +94,67 @@ public class Validator { public static void main(String[] args) throws Exception { System.out.println("FHIR Validation tool " + VersionUtil.getVersionString()); System.out.println("Detected Java version: " + 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, "-proxy"); + 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]); } - if (ParamUtils.hasParam(args, "-tests")) { - Utils.runValidationEngineTests(); - } else if (args.length == 0 || ParamUtils.hasParam(args, "help") || ParamUtils.hasParam(args, "?") || ParamUtils.hasParam(args, "-?") || ParamUtils.hasParam(args, "/?")) { - DisplayUtils.displayHelpDetails(); - } else if (ParamUtils.hasParam(args, "-compare")) { - DisplayUtils.printCliArgumentsAndInfo(args); - String dest = ParamUtils.getParam(args, "-dest"); + 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, "/?")) { + 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 - String txLog = Utils.getTerminologyServerLog(args); - ValidationEngine validator = Utils.getValidationEngine(args, txLog); - Utils.checkIGFileReferences(args); - ComparisonUtils.doLeftRightComparison(args, dest, validator); + String txLog = Common.getTerminologyServerLog(args); + ValidationEngine validator = Common.getValidationEngine(args, txLog); + Common.checkIGFileReferences(args); + Comparison.doLeftRightComparison(args, dest, validator); } } else { - DisplayUtils.printCliArgumentsAndInfo(args); - - String map = null; - List igs = new ArrayList(); - List questionnaires = new ArrayList(); - String txServer = "http://tx.fhir.org"; - boolean doNative = false; - boolean anyExtensionsAllowed = true; - boolean hintAboutNonMustSupport = false; - boolean recursive = false; - Locale locale = null; - List profiles = new ArrayList(); - EngineMode mode = EngineMode.VALIDATION; - String output = null; - Boolean canDoNative = null; - List sources = new ArrayList(); - Map locations = new HashMap(); - String sv = "current"; - String txLog = null; - String mapLog = null; - String lang = null; - String fhirpath = null; - String snomedCT = "900000000000207008"; - String targetVer = null; - boolean doDebug = false; - boolean assumeValidRestReferences = false; - - // load the parameters - so order doesn't matter - for (int i = 0; i < args.length; i++) { - if (args[i].equals("-version")) { - sv = args[++i]; - sv = VersionUtilities.getCurrentPackageVersion(sv); - } else if (args[i].equals("-output")) { - if (i + 1 == args.length) - throw new Error("Specified -output without indicating output file"); - else - output = args[++i]; - } else if (args[i].equals("-proxy")) { - i++; // ignore next parameter - } else if (args[i].equals("-profile")) { - String p = null; - if (i + 1 == args.length) - throw new Error("Specified -profile without indicating profile source"); - else { - p = args[++i]; - profiles.add(p); - } - if (p != null && i + 1 < args.length && args[i + 1].equals("@")) { - i++; - if (i + 1 == args.length) - throw new Error("Specified -profile with @ without indicating profile location"); - else - locations.put(p, args[++i]); - } - } else if (args[i].equals("-questionnaire")) { - if (i + 1 == args.length) - throw new Error("Specified -questionnaire without indicating questionnaire file"); - else - questionnaires.add(args[++i]); - } else if (args[i].equals("-native")) { - doNative = true; - } else if (args[i].equals("-assumeValidRestReferences")) { - assumeValidRestReferences = true; - } else if (args[i].equals("-debug")) { - doDebug = true; - } else if (args[i].equals("-sct")) { - String s = args[++i]; - snomedCT = SnomedVersion.resolveSnomedCTCode(s); - } else if (args[i].equals("-recurse")) { - recursive = true; - } else if (args[i].equals("-locale")) { - if (i + 1 == args.length) { - throw new Error("Specified -locale without indicating locale"); - } else { - locale = new Locale(args[++i]); - } - } else if (args[i].equals("-strictExtensions")) { - anyExtensionsAllowed = false; - } else if (args[i].equals("-hintAboutNonMustSupport")) { - hintAboutNonMustSupport = true; - } else if (args[i].equals("-to-version")) { - targetVer = args[++i]; - mode = EngineMode.VERSION; - } else if (args[i].equals("-do-native")) { - canDoNative = true; - } else if (args[i].equals("-no-native")) { - canDoNative = false; - } else if (args[i].equals("-transform")) { - map = args[++i]; - mode = EngineMode.TRANSFORM; - } else if (args[i].equals("-narrative")) { - mode = EngineMode.NARRATIVE; - } else if (args[i].equals("-snapshot")) { - mode = EngineMode.SNAPSHOT; - } else if (args[i].equals("-scan")) { - mode = EngineMode.SCAN; - } else if (args[i].equals("-tx")) { - if (i + 1 == args.length) - throw new Error("Specified -tx without indicating terminology server"); - else - txServer = "n/a".equals(args[++i]) ? null : args[i]; - } else if (args[i].equals("-txLog")) { - if (i + 1 == args.length) - throw new Error("Specified -txLog without indicating file"); - else - txLog = args[++i]; - } else if (args[i].equals("-log")) { - if (i + 1 == args.length) - throw new Error("Specified -log without indicating file"); - else - mapLog = args[++i]; - } else if (args[i].equals("-language")) { - if (i + 1 == args.length) - throw new Error("Specified -language without indicating language"); - else - lang = args[++i]; - } else if (args[i].equals("-ig") || args[i].equals("-defn")) { - if (i + 1 == args.length) - throw new Error("Specified " + args[i] + " without indicating ig file"); - else { - String s = args[++i]; - sv = Utils.getVersionFromIGName(null, s); - if (sv == null) { - igs.add(s); - } - } - } else if (args[i].equals("-map")) { - if (map == null) { - if (i + 1 == args.length) - throw new Error("Specified -map without indicating map file"); - else - map = args[++i]; - } else { - throw new Exception("Can only nominate a single -map parameter"); - } - } else if (args[i].startsWith("-x")) { - i++; - } else if (args[i].equals("-convert")) { - mode = EngineMode.CONVERT; - } else if (args[i].equals("-fhirpath")) { - mode = EngineMode.FHIRPATH; - if (fhirpath == null) - if (i + 1 == args.length) - throw new Error("Specified -fhirpath without indicating a FHIRPath expression"); - else - fhirpath = args[++i]; - else - throw new Exception("Can only nominate a single -fhirpath parameter"); - } else { - sources.add(args[i]); - } - } - if (sources.isEmpty()) - throw new Exception("Must provide at least one source file"); + Display.printCliArgumentsAndInfo(args); + CliContext cliContext = Params.loadCliContext(args); // 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(sv) + "#" + VersionUtilities.getCurrentVersion(sv); - System.out.println(" .. FHIR Version " + sv + ", definitions from " + definitions); - System.out.println(" .. connect to tx server @ " + txServer); - ValidationEngine validator = new ValidationEngine(definitions, txServer, txLog, FhirPublication.fromCode(sv), sv); - validator.setDebug(doDebug); - System.out.println(" (v" + validator.getContext().getVersion() + ")"); - for (String src : igs) { - System.out.println("+ .. load IG from " + src); - validator.loadIg(src, recursive); - } - validator.setQuestionnaires(questionnaires); - validator.setNative(doNative); - validator.setHintAboutNonMustSupport(hintAboutNonMustSupport); - validator.setAnyExtensionsAllowed(anyExtensionsAllowed); - validator.setLanguage(lang); - validator.setLocale(locale); - validator.setSnomedExtension(snomedCT); - validator.setAssumeValidRestReferences(assumeValidRestReferences); + String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv()); + ValidationEngine validator = ValidationUtils.getValidator(cliContext, definitions); - IParser x; - if (output != null && output.endsWith(".json")) - x = new JsonParser(); - else - x = new XmlParser(); - x.setOutputStyle(OutputStyle.PRETTY); - - if (mode == EngineMode.VERSION) { - if (sources.size() > 1) { - throw new Exception("Can only have one source when converting versions (found " + sources + ")"); - } - if (targetVer == null) { - throw new Exception("Must provide a map when converting versions"); - } - if (output == null) { - throw new Exception("Must nominate an output when converting versions"); - } - try { - if (mapLog != null) { - validator.setMapLog(mapLog); - } - byte[] r = validator.transformVersion(sources.get(0), targetVer, output.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML, canDoNative); - System.out.println(" ...success"); - TextFile.bytesToFile(r, output); - } catch (Exception e) { - System.out.println(" ...Failure: " + e.getMessage()); - e.printStackTrace(); - } - } else if (mode == EngineMode.TRANSFORM) { - if (sources.size() > 1) - throw new Exception("Can only have one source when doing a transform (found " + sources + ")"); - if (txServer == null) - throw new Exception("Must provide a terminology server when doing a transform"); - if (map == null) - throw new Exception("Must provide a map when doing a transform"); - try { - validator.setMapLog(mapLog); - org.hl7.fhir.r5.elementmodel.Element r = validator.transform(sources.get(0), map); - System.out.println(" ...success"); - if (output != null) { - FileOutputStream s = new FileOutputStream(output); - if (output != null && output.endsWith(".json")) - new org.hl7.fhir.r5.elementmodel.JsonParser(validator.getContext()).compose(r, s, OutputStyle.PRETTY, null); - else - new org.hl7.fhir.r5.elementmodel.XmlParser(validator.getContext()).compose(r, s, OutputStyle.PRETTY, null); - s.close(); - } - } catch (Exception e) { - System.out.println(" ...Failure: " + e.getMessage()); - e.printStackTrace(); - } - } else if (mode == EngineMode.NARRATIVE) { - DomainResource r = validator.generate(sources.get(0), sv); - System.out.println(" ...generated narrative successfully"); - if (output != null) { - validator.handleOutput(r, output, sv); - } - } else if (mode == EngineMode.SNAPSHOT) { - StructureDefinition r = validator.snapshot(sources.get(0), sv); - System.out.println(" ...generated snapshot successfully"); - if (output != null) { - validator.handleOutput(r, output, sv); - } - } else if (mode == EngineMode.CONVERT) { - validator.convert(sources.get(0), output); - System.out.println(" ...convert"); - } else if (mode == EngineMode.FHIRPATH) { - System.out.println(" ...evaluating " + fhirpath); - System.out.println(validator.evaluateFhirPath(sources.get(0), fhirpath)); + if (cliContext.getMode() == EngineMode.VERSION) { + ValidationUtils.transformVersion(cliContext, validator); + } else if (cliContext.getMode() == EngineMode.TRANSFORM) { + ValidationUtils.transform(cliContext, validator); + } else if (cliContext.getMode() == EngineMode.NARRATIVE) { + ValidationUtils.generateNarrative(cliContext, validator); + } else if (cliContext.getMode() == EngineMode.SNAPSHOT) { + ValidationUtils.generateSnapshot(cliContext, validator); + } else if (cliContext.getMode() == EngineMode.CONVERT) { + ValidationUtils.convertSources(cliContext, validator); + } else if (cliContext.getMode() == EngineMode.FHIRPATH) { + ValidationUtils.evaluateFhirpath(cliContext, validator); } else { - if (definitions == null) + if (definitions == null) { throw new Exception("Must provide a defn when doing validation"); - for (String s : profiles) { + } + 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); - validator.loadProfile(locations.getOrDefault(s, s)); + validator.loadProfile(cliContext.getLocations().getOrDefault(s, s)); } } - if (mode == EngineMode.SCAN) { - if (Utilities.noString(output)) - throw new Exception("Output parameter required when scanning"); - if (!(new File(output).isDirectory())) - throw new Exception("Output '" + output + "' must be a directory when scanning"); - System.out.println(" .. scan " + sources + " against loaded IGs"); - Set urls = new HashSet<>(); - for (ImplementationGuide ig : validator.getContext().allImplementationGuides()) { - if (ig.getUrl().contains("/ImplementationGuide") && !ig.getUrl().equals("http://hl7.org/fhir/ImplementationGuide/fhir")) - urls.add(ig.getUrl()); - } - List res = validator.validateScan(sources, urls); - validator.genScanOutput(output, res); - System.out.println("Done. output in " + Utilities.path(output, "scan.html")); + if (cliContext.getMode() == EngineMode.SCAN) { + ValidationUtils.validateScan(cliContext, validator); } else { - if (profiles.size() > 0) - System.out.println(" .. validate " + sources + " against " + profiles.toString()); - else - System.out.println(" .. validate " + sources); - validator.prepare(); // generate any missing snapshots - Resource r = validator.validate(sources, profiles); - int ec = 0; - if (output == null) { - if (r instanceof Bundle) - for (BundleEntryComponent e : ((Bundle) r).getEntry()) - ec = displayOO((OperationOutcome) e.getResource()) + ec; - else - ec = displayOO((OperationOutcome) r); - } else { - FileOutputStream s = new FileOutputStream(output); - x.compose(s, r); - s.close(); - } - System.exit(ec > 0 ? 1 : 0); + ValidationUtils.validateSources(cliContext, validator); } } } } - - private static String getGitBuild() { - return "??"; - } - - private static int displayOO(OperationOutcome oo) { - int error = 0; - int warn = 0; - int info = 0; - String file = ToolingExtensions.readStringExtension(oo, ToolingExtensions.EXT_OO_FILE); - - for (OperationOutcomeIssueComponent issue : oo.getIssue()) { - if (issue.getSeverity() == OperationOutcome.IssueSeverity.FATAL || issue.getSeverity() == OperationOutcome.IssueSeverity.ERROR) - error++; - else if (issue.getSeverity() == OperationOutcome.IssueSeverity.WARNING) - warn++; - else - info++; - } - - System.out.println((error == 0 ? "Success..." : "*FAILURE* ") + "validating " + file + ": " + " error:" + Integer.toString(error) + " warn:" + Integer.toString(warn) + " info:" + Integer.toString(info)); - for (OperationOutcomeIssueComponent issue : oo.getIssue()) { - System.out.println(getIssueSummary(issue)); - } - System.out.println(); - return error; - } - - private static String getIssueSummary(OperationOutcomeIssueComponent issue) { - String loc = null; - if (issue.hasExpression()) { - int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1); - int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1); - loc = issue.getExpression().get(0).asStringValue() + (line >= 0 && col >= 0 ? " (line " + Integer.toString(line) + ", col" + Integer.toString(col) + ")" : ""); - } else if (issue.hasLocation()) { - loc = issue.getLocation().get(0).asStringValue(); - } else { - int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1); - int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1); - loc = (line >= 0 && col >= 0 ? "line " + Integer.toString(line) + ", col" + Integer.toString(col) : "??"); - } - return " " + issue.getSeverity().getDisplay() + " @ " + loc + " : " + issue.getDetails().getText(); - } - } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/CliContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/CliContext.java index 63661c8fe..27942ef76 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/CliContext.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/CliContext.java @@ -4,6 +4,9 @@ import org.hl7.fhir.validation.Validator; import java.util.*; +/** + * A POJO for storing the flags/values for the CLI validator. + */ public class CliContext { private String map = null; @@ -26,8 +29,261 @@ public class CliContext { private String mapLog = null; private String lang = null; private String fhirpath = null; - private String snomedCT = "900000000000207008"; + private String snomedCT = SnomedVersion.INTL.getCode(); private String targetVer = null; private boolean doDebug = false; private boolean assumeValidRestReferences = false; + + public String getMap() { + return map; + } + + public CliContext setMap(String map) { + this.map = map; + return this; + } + + public List getIgs() { + return igs; + } + + public CliContext setIgs(List igs) { + this.igs = igs; + return this; + } + + public CliContext addIg(String ig) { + if (this.igs == null) { + this.igs = new ArrayList<>(); + } + this.igs.add(ig); + return this; + } + + public List getQuestionnaires() { + return questionnaires; + } + + public CliContext setQuestionnaires(List questionnaires) { + this.questionnaires = questionnaires; + return this; + } + + public CliContext addQuestionnaire(String questionnaire) { + if (this.questionnaires == null) { + this.questionnaires = new ArrayList<>(); + } + this.questionnaires.add(questionnaire); + return this; + } + + public String getTxServer() { + return txServer; + } + + public CliContext setTxServer(String txServer) { + this.txServer = txServer; + return this; + } + + public boolean isDoNative() { + return doNative; + } + + public CliContext setDoNative(boolean doNative) { + this.doNative = doNative; + return this; + } + + public boolean isAnyExtensionsAllowed() { + return anyExtensionsAllowed; + } + + public CliContext setAnyExtensionsAllowed(boolean anyExtensionsAllowed) { + this.anyExtensionsAllowed = anyExtensionsAllowed; + return this; + } + + public boolean isHintAboutNonMustSupport() { + return hintAboutNonMustSupport; + } + + public CliContext setHintAboutNonMustSupport(boolean hintAboutNonMustSupport) { + this.hintAboutNonMustSupport = hintAboutNonMustSupport; + return this; + } + + public boolean isRecursive() { + return recursive; + } + + public CliContext setRecursive(boolean recursive) { + this.recursive = recursive; + return this; + } + + public Locale getLocale() { + return locale; + } + + public CliContext setLocale(Locale locale) { + this.locale = locale; + return this; + } + + public List getProfiles() { + return profiles; + } + + public CliContext setProfiles(List profiles) { + this.profiles = profiles; + return this; + } + + public CliContext addProfile(String profile) { + if (this.profiles == null) { + this.profiles = new ArrayList<>(); + } + this.profiles.add(profile); + return this; + } + + public Validator.EngineMode getMode() { + return mode; + } + + public CliContext setMode(Validator.EngineMode mode) { + this.mode = mode; + return this; + } + + public String getOutput() { + return output; + } + + public CliContext setOutput(String output) { + this.output = output; + return this; + } + + public Boolean getCanDoNative() { + return canDoNative; + } + + public CliContext setCanDoNative(Boolean canDoNative) { + this.canDoNative = canDoNative; + return this; + } + + public List getSources() { + return sources; + } + + public CliContext setSources(List sources) { + this.sources = sources; + return this; + } + + public CliContext addSource(String source) { + if (this.sources == null) { + this.sources = new ArrayList<>(); + } + this.sources.add(source); + return this; + } + + public Map getLocations() { + return locations; + } + + public CliContext setLocations(Map locations) { + this.locations = locations; + return this; + } + + public CliContext addLocation(String profile, String location) { + this.locations.put(profile, location); + return this; + } + + public String getSv() { + return sv; + } + + public CliContext setSv(String sv) { + this.sv = sv; + return this; + } + + public String getTxLog() { + return txLog; + } + + public CliContext setTxLog(String txLog) { + this.txLog = txLog; + return this; + } + + public String getMapLog() { + return mapLog; + } + + public CliContext setMapLog(String mapLog) { + this.mapLog = mapLog; + return this; + } + + public String getLang() { + return lang; + } + + public CliContext setLang(String lang) { + this.lang = lang; + return this; + } + + public String getFhirpath() { + return fhirpath; + } + + public CliContext setFhirpath(String fhirpath) { + this.fhirpath = fhirpath; + return this; + } + + public String getSnomedCT() { + return snomedCT; + } + + public CliContext setSnomedCT(String snomedCT) { + this.snomedCT = SnomedVersion.resolveSnomedCTCode(snomedCT); + return this; + } + + public String getTargetVer() { + return targetVer; + } + + public CliContext setTargetVer(String targetVer) { + this.targetVer = targetVer; + return this; + } + + public boolean isDoDebug() { + return doDebug; + } + + public CliContext setDoDebug(boolean doDebug) { + this.doDebug = doDebug; + return this; + } + + public boolean isAssumeValidRestReferences() { + return assumeValidRestReferences; + } + + public CliContext setAssumeValidRestReferences(boolean assumeValidRestReferences) { + this.assumeValidRestReferences = assumeValidRestReferences; + return this; + } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Utils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Common.java similarity index 76% rename from org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Utils.java rename to org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Common.java index 37cd63218..0e3e9adde 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Utils.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Common.java @@ -1,19 +1,16 @@ package org.hl7.fhir.validation.cliutils; -import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.FhirPublication; -import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.validation.ValidationEngine; import java.io.File; -public class Utils { - +public class Common { public static String getVersion(String[] args) { - String v = ParamUtils.getParam(args, "-version"); + String v = Params.getParam(args, "-version"); if (v == null) { v = "current"; for (int i = 0; i < args.length; i++) { @@ -22,7 +19,7 @@ public class Utils { throw new Error("Specified -ig without indicating ig file"); else { String n = args[i + 1]; - v = Utils.getVersionFromIGName(v, n); + v = Common.getVersionFromIGName(v, n); } } } @@ -42,11 +39,11 @@ public class Utils { /** * Evaluates the current implementation guide file name and sets the current version accordingly. - * + *

* If igFileName is not one of the known patterns, will return whatever value is passed in as default. * * @param defaultValue Version to return if no associated version can be determined from passed in igFileName - * @param igFileName Name of the implementation guide + * @param igFileName Name of the implementation guide * @return */ public static String getVersionFromIGName(String defaultValue, String igFileName) { @@ -82,15 +79,15 @@ public class Utils { public static String getTerminologyServerLog(String[] args) { String txLog = null; - if (ParamUtils.hasParam(args, "-txLog")) { - txLog = ParamUtils.getParam(args, "-txLog"); + if (Params.hasParam(args, "-txLog")) { + txLog = Params.getParam(args, "-txLog"); new File(txLog).delete(); } return txLog; } public static ValidationEngine getValidationEngine(String[] args, String txLog) throws Exception { - String v = Utils.getVersion(args); + String v = Common.getVersion(args); String definitions = VersionUtilities.packageForVersion(v) + "#" + v; System.out.println("Loading (v = " + v + ", tx server http://tx.fhir.org)"); return new ValidationEngine(definitions, "http://tx.fhir.org", txLog, FhirPublication.fromCode(v), v); @@ -110,21 +107,4 @@ public class Utils { } } } - - private static Resource loadResource(String[] args, String param, SimpleWorkerContext context) { - String resString = ParamUtils.getParam(args, param); - Resource resource = context.fetchResource(Resource.class, resString); - if (resource == null) { - System.out.println("Unable to locate resource for " + param + ", " + resString); - } - return resource; - } - - public static Resource getRightResource(String[] args, SimpleWorkerContext context) { - return loadResource(args, "-right", context); - } - - public static Resource getLeftResource(String[] args, SimpleWorkerContext context) { - return loadResource(args, "-left", context); - } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ComparisonUtils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Comparison.java similarity index 87% rename from org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ComparisonUtils.java rename to org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Comparison.java index af39679c3..29612713e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ComparisonUtils.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Comparison.java @@ -21,27 +21,27 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; -public class ComparisonUtils { +public class Comparison { public static void doLeftRightComparison(String[] args, String dest, ValidationEngine validator) throws IOException { // ok now set up the comparison - String left = ParamUtils.getParam(args, "-left"); - String right = ParamUtils.getParam(args, "-right"); + String left = Params.getParam(args, Params.LEFT); + String right = Params.getParam(args, Params.RIGHT); - Resource resLeft = validator.getContext().fetchResource(Resource.class, left); + Resource resLeft = validator.getContext().fetchResource(Resource.class, left); Resource resRight = validator.getContext().fetchResource(Resource.class, right); if (resLeft == null) { - System.out.println("Unable to locate left resource " +left); + System.out.println("Unable to locate left resource " + left); } if (resRight == null) { - System.out.println("Unable to locate right resource " +right); + System.out.println("Unable to locate right resource " + right); } if (resLeft != null && resRight != null) { if (resLeft instanceof StructureDefinition && resRight instanceof StructureDefinition) { - ComparisonUtils.compareStructureDefinitions(dest, validator, left, right, (StructureDefinition) resLeft, (StructureDefinition) resRight); + Comparison.compareStructureDefinitions(dest, validator, left, right, (StructureDefinition) resLeft, (StructureDefinition) resRight); } else if (resLeft instanceof CapabilityStatement && resRight instanceof CapabilityStatement) { - ComparisonUtils.compareCapabilityStatements(args, dest, validator, left, right, (CanonicalResource) resLeft, (CanonicalResource) resRight); + Comparison.compareCapabilityStatements(args, dest, validator, left, right, (CanonicalResource) resLeft, (CanonicalResource) resRight); } else System.out.println("Unable to compare left resource " + left + " (" + resLeft.fhirType() + ") with right resource " + right + " (" + resRight.fhirType() + ")"); } @@ -90,7 +90,7 @@ public class ComparisonUtils { } private static String chooseName(String[] args, String name, CanonicalResource mr) { - String s = ParamUtils.getParam(args, "-" + name); + String s = Params.getParam(args, "-" + name); if (Utilities.noString(s)) s = mr.present(); return s; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/DisplayUtils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Display.java similarity index 95% rename from org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/DisplayUtils.java rename to org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Display.java index f5a7f4c18..bb993edc7 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/DisplayUtils.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Display.java @@ -7,7 +7,7 @@ import org.hl7.fhir.utilities.cache.ToolsVersion; import java.io.IOException; -public class DisplayUtils { +public class Display { public static void printCliArgumentsAndInfo(String[] args) throws IOException { System.out.print("Arguments:"); @@ -27,8 +27,8 @@ public class DisplayUtils { 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("* 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"); @@ -43,8 +43,8 @@ public class DisplayUtils { 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(" 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"); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamArg.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamArg.java deleted file mode 100644 index b27ac9050..000000000 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamArg.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.hl7.fhir.validation.cliutils; - -public enum ParamArg { - VERSION("-version"), - OUTPUT("-output"), - PROXY("-proxy"), - PROFILE("-profile"), - QUESTIONNAIRE("-questionnaire"), - NATIVE("-native"), - ASSUME_VALID_REST_REF("-assumeValidRestReferences"), - DEBUG("-debug"), - SCT("-sct"), - RECURSE("-recurse"), - LOCALE("-locale"), - STRICT_EXTENSIONS("-strictExtensions"), - HINT_ABOUT_NON_MUST_SUPPORT("-hintAboutNonMustSupport"), - TO_VERSION("-to-version"), - DO_NATIVE("-do-native"), - NO_NATIVE("-no-native"), - TRANSFORM("-transform"), - NARRATIVE("-narrative"), - SNAPSHOT("-snapshot"), - SCAN("-scan"), - TERMINOLOGY("-tx"), - TERMINOLOGY_LOG("-txLog"); - - private final String code; - - ParamArg(String code) { - this.code = code; - } - -} - - -// } else if (args[i].equals("-log")) { -// if (i + 1 == args.length) -// throw new Error("Specified -log without indicating file"); -// else -// mapLog = args[++i]; -// } else if (args[i].equals("-language")) { -// if (i + 1 == args.length) -// throw new Error("Specified -language without indicating language"); -// else -// lang = args[++i]; -// } else if (args[i].equals("-ig") || args[i].equals("-defn")) { -// if (i + 1 == args.length) -// throw new Error("Specified " + args[i] + " without indicating ig file"); -// else { -// String s = args[++i]; -// sv = Utils.getVersionFromIGName(null, s); -// if (sv == null) { -// igs.add(s); -// } -// } -// } else if (args[i].equals("-map")) { -// if (map == null) { -// if (i + 1 == args.length) -// throw new Error("Specified -map without indicating map file"); -// else -// map = args[++i]; -// } else { -// throw new Exception("Can only nominate a single -map parameter"); -// } -// } else if (args[i].startsWith("-x")) { -// i++; -// } else if (args[i].equals("-convert")) { -// mode = EngineMode.CONVERT; -// } else if (args[i].equals("-fhirpath")) { -// mode = EngineMode.FHIRPATH; -// if (fhirpath == null) -// if (i + 1 == args.length) -// throw new Error("Specified -fhirpath without indicating a FHIRPath expression"); -// else -// fhirpath = args[++i]; -// else -// throw new Exception("Can only nominate a single -fhirpath parameter"); -// } else { -// sources.add(args[i]); -// } -// } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamUtils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamUtils.java deleted file mode 100644 index 32913524d..000000000 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ParamUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.hl7.fhir.validation.cliutils; - -import java.util.Arrays; - -public class ParamUtils { - - /** - * Checks the list of passed in params to see if it contains the passed in param. - * - * @param args Array of params to search. - * @param param {@link String} param to search for. - * @return {@link Boolean#TRUE} if the list contains the given param. - */ - public static boolean hasParam(String[] args, String param) { - return Arrays.asList(args).contains(param); - } - - /** - * Fetches the vlaue for the passed in param from the provided list of params. - * - * @param args Array of params to search. - * @param param {@link String} param keyword to search for. - * @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]; - return null; - } - -} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Params.java new file mode 100644 index 000000000..cb9927640 --- /dev/null +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/Params.java @@ -0,0 +1,210 @@ +package org.hl7.fhir.validation.cliutils; + +import org.hl7.fhir.utilities.VersionUtilities; +import org.hl7.fhir.validation.Validator; + +import java.util.Arrays; +import java.util.Locale; + +public class Params { + + public static final String VERSION = "-version"; + public static final String OUTPUT = "-output"; + public static final String PROXY = "-proxy"; + public static final String PROFILE = "-profile"; + public static final String QUESTIONNAIRE = "-questionnaire"; + public static final String NATIVE = "-native"; + public static final String ASSUME_VALID_REST_REF = "-assumeValidRestReferences"; + public static final String DEBUG = "-debug"; + public static final String SCT = "-sct"; + public static final String RECURSE = "-recurse"; + public static final String LOCALE = "-locale"; + public static final String STRICT_EXTENSIONS = "-strictExtensions"; + public static final String HINT_ABOUT_NON_MUST_SUPPORT = "-hintAboutNonMustSupport"; + public static final String TO_VERSION = "-to-version"; + public static final String DO_NATIVE = "-do-native"; + public static final String NO_NATIVE = "-no-native"; + public static final String TRANSFORM = "-transform"; + public static final String NARRATIVE = "-narrative"; + public static final String SNAPSHOT = "-snapshot"; + public static final String SCAN = "-scan"; + public static final String TERMINOLOGY = "-tx"; + public static final String TERMINOLOGY_LOG = "-txLog"; + public static final String LOG = "-log"; + public static final String LANGUAGE = "-language"; + public static final String IMPLEMENTATION_GUIDE = "-ig"; + public static final String DEFINITION = "defn"; + public static final String MAP = "-map"; + public static final String X = "-x"; + public static final String CONVERT = "-convert"; + public static final String FHIRPATH = "-fhirpath"; + public static final String TEST = "-tests"; + public static final String HELP = "help"; + public static final String COMPARE = "-compare"; + public static final String DESTINATION = "-dest"; + public static final String LEFT = "-left"; + public static final String RIGHT = "-right"; + + /** + * Checks the list of passed in params to see if it contains the passed in param. + * + * @param args Array of params to search. + * @param param {@link String} param to search for. + * @return {@link Boolean#TRUE} if the list contains the given param. + */ + public static boolean hasParam(String[] args, String param) { + return Arrays.asList(args).contains(param); + } + + /** + * Fetches the vlaue for the passed in param from the provided list of params. + * + * @param args Array of params to search. + * @param param {@link String} param keyword to search for. + * @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]; + return null; + } + + /** + * TODO Don't do this all in one for loop. + * + * @param args + * @return + * @throws Exception + */ + public static CliContext loadCliContext(String[] args) throws Exception { + CliContext cliContext = new CliContext(); + + // load the parameters - so order doesn't matter + for (int i = 0; i < args.length; i++) { + if (args[i].equals(VERSION)) { + cliContext.setSv(VersionUtilities.getCurrentPackageVersion(args[++i])); + } else if (args[i].equals(OUTPUT)) { + if (i + 1 == args.length) + throw new Error("Specified -output without indicating output file"); + else + cliContext.setOutput(args[++i]); + } else if (args[i].equals(PROXY)) { + i++; // ignore next parameter + } else if (args[i].equals(PROFILE)) { + String p = null; + if (i + 1 == args.length) + throw new Error("Specified -profile without indicating profile source"); + else { + p = args[++i]; + cliContext.addProfile(args[++i]); + } + if (p != null && i + 1 < args.length && args[i + 1].equals("@")) { + i++; + if (i + 1 == args.length) + throw new Error("Specified -profile with @ without indicating profile location"); + else + cliContext.addLocation(p, args[++i]); + } + } else if (args[i].equals(QUESTIONNAIRE)) { + if (i + 1 == args.length) + throw new Error("Specified -questionnaire without indicating questionnaire file"); + else + cliContext.addQuestionnaire(args[++i]); + } else if (args[i].equals(NATIVE)) { + cliContext.setDoNative(true); + } else if (args[i].equals(ASSUME_VALID_REST_REF)) { + cliContext.setAssumeValidRestReferences(true); + } else if (args[i].equals(DEBUG)) { + cliContext.setDoDebug(true); + } else if (args[i].equals(SCT)) { + cliContext.setSnomedCT(args[++i]); + } else if (args[i].equals(RECURSE)) { + cliContext.setRecursive(true); + } else if (args[i].equals(LOCALE)) { + if (i + 1 == args.length) { + throw new Error("Specified -locale without indicating locale"); + } else { + cliContext.setLocale(new Locale(args[++i])); + } + } else if (args[i].equals(STRICT_EXTENSIONS)) { + cliContext.setAnyExtensionsAllowed(false); + } 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); + } 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); + } else if (args[i].equals(NARRATIVE)) { + cliContext.setMode(Validator.EngineMode.NARRATIVE); + } else if (args[i].equals(SNAPSHOT)) { + cliContext.setMode(Validator.EngineMode.SNAPSHOT); + } else if (args[i].equals(SCAN)) { + cliContext.setMode(Validator.EngineMode.SCAN); + } else if (args[i].equals(TERMINOLOGY)) { + if (i + 1 == args.length) + throw new Error("Specified -tx without indicating terminology server"); + else + cliContext.setTxServer("n/a".equals(args[++i]) ? null : args[i]); + } else if (args[i].equals(TERMINOLOGY_LOG)) { + if (i + 1 == args.length) + throw new Error("Specified -txLog without indicating file"); + else + cliContext.setTxLog(args[++i]); + } else if (args[i].equals(LOG)) { + if (i + 1 == args.length) + throw new Error("Specified -log without indicating file"); + else + cliContext.setMapLog(args[++i]); + } else if (args[i].equals(LANGUAGE)) { + if (i + 1 == args.length) + throw new Error("Specified -language without indicating language"); + else + cliContext.setLang(args[++i]); + } else if (args[i].equals(IMPLEMENTATION_GUIDE) || args[i].equals(DEFINITION)) { + if (i + 1 == args.length) + throw new Error("Specified " + args[i] + " without indicating ig file"); + else { + String s = args[++i]; + cliContext.setSv(Common.getVersionFromIGName(null, s)); + if (cliContext.getSv() == null) { + cliContext.addIg(s); + } + } + } else if (args[i].equals(MAP)) { + if (cliContext.getMap() == null) { + if (i + 1 == args.length) + throw new Error("Specified -map without indicating map file"); + else + cliContext.setMap(args[++i]); + } else { + throw new Exception("Can only nominate a single -map parameter"); + } + } else if (args[i].startsWith(X)) { + i++; + } else if (args[i].equals(CONVERT)) { + cliContext.setMode(Validator.EngineMode.CONVERT); + } else if (args[i].equals(FHIRPATH)) { + cliContext.setMode(Validator.EngineMode.FHIRPATH); + if (cliContext.getFhirpath() == null) + if (i + 1 == args.length) + throw new Error("Specified -fhirpath without indicating a FHIRPath expression"); + else + cliContext.setFhirpath(args[++i]); + else + throw new Exception("Can only nominate a single -fhirpath parameter"); + } else { + cliContext.addSource(args[i]); + } + } + if (cliContext.getSources().isEmpty()) + throw new Exception("Must provide at least one source file"); + return cliContext; + } +} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/SnomedVersion.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/SnomedVersion.java index ea26fbfa6..f18112090 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/SnomedVersion.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/SnomedVersion.java @@ -24,6 +24,14 @@ public enum SnomedVersion { this.code = code; } + public String getLang() { + return lang; + } + + public String getCode() { + return code; + } + public static String resolveSnomedCTCode(String s) { String foundCode; Optional opt = Arrays.stream(values()) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ValidationUtils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ValidationUtils.java new file mode 100644 index 000000000..a5141ce14 --- /dev/null +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cliutils/ValidationUtils.java @@ -0,0 +1,198 @@ +package org.hl7.fhir.validation.cliutils; + +import org.hl7.fhir.r5.elementmodel.Manager; +import org.hl7.fhir.r5.formats.IParser; +import org.hl7.fhir.r5.formats.JsonParser; +import org.hl7.fhir.r5.formats.XmlParser; +import org.hl7.fhir.r5.model.*; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.validation.ValidationEngine; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ValidationUtils { + public static void validateSources(CliContext cliContext, ValidationEngine validator) throws Exception { + if (cliContext.getProfiles().size() > 0) + System.out.println(" .. validate " + cliContext.getSources() + " against " + cliContext.getProfiles().toString()); + else + System.out.println(" .. validate " + cliContext.getSources()); + validator.prepare(); // generate any missing snapshots + Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles()); + int ec = 0; + if (cliContext.getOutput() == null) { + if (r instanceof Bundle) + for (Bundle.BundleEntryComponent e : ((Bundle) r).getEntry()) + ec = displayOperationOutcome((OperationOutcome) e.getResource()) + ec; + else + ec = displayOperationOutcome((OperationOutcome) r); + } else { + IParser x; + if (cliContext.getOutput() != null && cliContext.getOutput().endsWith(".json")) { + x = new JsonParser(); + } else { + x = new XmlParser(); + } + x.setOutputStyle(IParser.OutputStyle.PRETTY); + FileOutputStream s = new FileOutputStream(cliContext.getOutput()); + x.compose(s, r); + s.close(); + } + System.exit(ec > 0 ? 1 : 0); + } + + public static void validateScan(CliContext cliContext, ValidationEngine validator) throws Exception { + if (Utilities.noString(cliContext.getOutput())) + throw new Exception("Output parameter required when scanning"); + if (!(new File(cliContext.getOutput()).isDirectory())) + throw new Exception("Output '" + cliContext.getOutput() + "' must be a directory when scanning"); + System.out.println(" .. scan " + cliContext.getSources() + " against loaded IGs"); + Set urls = new HashSet<>(); + for (ImplementationGuide ig : validator.getContext().allImplementationGuides()) { + if (ig.getUrl().contains("/ImplementationGuide") && !ig.getUrl().equals("http://hl7.org/fhir/ImplementationGuide/fhir")) + urls.add(ig.getUrl()); + } + List res = validator.validateScan(cliContext.getSources(), urls); + validator.genScanOutput(cliContext.getOutput(), res); + System.out.println("Done. output in " + Utilities.path(cliContext.getOutput(), "scan.html")); + } + + public static void convertSources(CliContext cliContext, ValidationEngine validator) throws Exception { + validator.convert(cliContext.getSources().get(0), cliContext.getOutput()); + System.out.println(" ...convert"); + } + + public static void evaluateFhirpath(CliContext cliContext, ValidationEngine validator) throws Exception { + System.out.println(" ...evaluating " + cliContext.getFhirpath()); + System.out.println(validator.evaluateFhirPath(cliContext.getSources().get(0), cliContext.getFhirpath())); + } + + public static void generateSnapshot(CliContext cliContext, ValidationEngine validator) throws Exception { + StructureDefinition r = validator.snapshot(cliContext.getSources().get(0), cliContext.getSv()); + System.out.println(" ...generated snapshot successfully"); + if (cliContext.getOutput() != null) { + validator.handleOutput(r, cliContext.getOutput(), cliContext.getSv()); + } + } + + public static void generateNarrative(CliContext cliContext, ValidationEngine validator) throws Exception { + DomainResource r = validator.generate(cliContext.getSources().get(0), cliContext.getSv()); + System.out.println(" ...generated narrative successfully"); + if (cliContext.getOutput() != null) { + validator.handleOutput(r, cliContext.getOutput(), cliContext.getSv()); + } + } + + public static void transform(CliContext cliContext, ValidationEngine validator) throws Exception { + if (cliContext.getSources().size() > 1) + throw new Exception("Can only have one source when doing a transform (found " + cliContext.getSources() + ")"); + if (cliContext.getTxServer() == null) + throw new Exception("Must provide a terminology server when doing a transform"); + if (cliContext.getMap() == null) + throw new Exception("Must provide a map when doing a transform"); + try { + validator.setMapLog(cliContext.getMapLog()); + org.hl7.fhir.r5.elementmodel.Element r = validator.transform(cliContext.getSources().get(0), cliContext.getMap()); + System.out.println(" ...success"); + if (cliContext.getOutput() != null) { + FileOutputStream s = new FileOutputStream(cliContext.getOutput()); + if (cliContext.getOutput() != null && cliContext.getOutput().endsWith(".json")) + new org.hl7.fhir.r5.elementmodel.JsonParser(validator.getContext()).compose(r, s, IParser.OutputStyle.PRETTY, null); + else + new org.hl7.fhir.r5.elementmodel.XmlParser(validator.getContext()).compose(r, s, IParser.OutputStyle.PRETTY, null); + s.close(); + } + } catch (Exception e) { + System.out.println(" ...Failure: " + e.getMessage()); + e.printStackTrace(); + } + } + + public static void transformVersion(CliContext cliContext, ValidationEngine validator) throws Exception { + if (cliContext.getSources().size() > 1) { + throw new Exception("Can only have one source when converting versions (found " + cliContext.getSources() + ")"); + } + if (cliContext.getTargetVer() == null) { + throw new Exception("Must provide a map when converting versions"); + } + if (cliContext.getOutput() == null) { + throw new Exception("Must nominate an output when converting versions"); + } + try { + if (cliContext.getMapLog() != null) { + validator.setMapLog(cliContext.getMapLog()); + } + byte[] r = validator.transformVersion(cliContext.getSources().get(0), cliContext.getTargetVer(), cliContext.getOutput().endsWith(".json") ? Manager.FhirFormat.JSON : Manager.FhirFormat.XML, cliContext.getCanDoNative()); + System.out.println(" ...success"); + TextFile.bytesToFile(r, cliContext.getOutput()); + } catch (Exception e) { + System.out.println(" ...Failure: " + e.getMessage()); + e.printStackTrace(); + } + } + + public static ValidationEngine getValidator(CliContext cliContext, String definitions) throws Exception { + System.out.println(" .. FHIR Version " + cliContext.getSv() + ", definitions from " + definitions); + System.out.println(" .. connect to tx server @ " + cliContext.getTxServer()); + ValidationEngine validator = new ValidationEngine(definitions, cliContext.getTxServer(), cliContext.getTxLog(), FhirPublication.fromCode(cliContext.getSv()), cliContext.getSv()); + validator.setDebug(cliContext.isDoDebug()); + System.out.println(" (v" + validator.getContext().getVersion() + ")"); + for (String src : cliContext.getIgs()) { + System.out.println("+ .. load IG from " + src); + validator.loadIg(src, cliContext.isRecursive()); + } + validator.setQuestionnaires(cliContext.getQuestionnaires()); + validator.setNative(cliContext.isDoNative()); + validator.setHintAboutNonMustSupport(cliContext.isHintAboutNonMustSupport()); + validator.setAnyExtensionsAllowed(cliContext.isAnyExtensionsAllowed()); + validator.setLanguage(cliContext.getLang()); + validator.setLocale(cliContext.getLocale()); + validator.setSnomedExtension(cliContext.getSnomedCT()); + validator.setAssumeValidRestReferences(cliContext.isAssumeValidRestReferences()); + return validator; + } + + public static int displayOperationOutcome(OperationOutcome oo) { + int error = 0; + int warn = 0; + int info = 0; + String file = ToolingExtensions.readStringExtension(oo, ToolingExtensions.EXT_OO_FILE); + + for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) { + if (issue.getSeverity() == OperationOutcome.IssueSeverity.FATAL || issue.getSeverity() == OperationOutcome.IssueSeverity.ERROR) + error++; + else if (issue.getSeverity() == OperationOutcome.IssueSeverity.WARNING) + warn++; + else + info++; + } + + System.out.println((error == 0 ? "Success..." : "*FAILURE* ") + "validating " + file + ": " + " error:" + Integer.toString(error) + " warn:" + Integer.toString(warn) + " info:" + Integer.toString(info)); + for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) { + System.out.println(getIssueSummary(issue)); + } + System.out.println(); + return error; + } + + private static String getIssueSummary(OperationOutcome.OperationOutcomeIssueComponent issue) { + String loc = null; + if (issue.hasExpression()) { + int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1); + int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1); + loc = issue.getExpression().get(0).asStringValue() + (line >= 0 && col >= 0 ? " (line " + Integer.toString(line) + ", col" + Integer.toString(col) + ")" : ""); + } else if (issue.hasLocation()) { + loc = issue.getLocation().get(0).asStringValue(); + } else { + int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1); + int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1); + loc = (line >= 0 && col >= 0 ? "line " + Integer.toString(line) + ", col" + Integer.toString(col) : "??"); + } + return " " + issue.getSeverity().getDisplay() + " @ " + loc + " : " + issue.getDetails().getText(); + } +}