add -output-style parameter

This commit is contained in:
Grahame Grieve 2021-10-21 12:56:56 +11:00
parent 09d717a2ba
commit 54d31a33dc
6 changed files with 179 additions and 68 deletions

View File

@ -97,6 +97,9 @@ public class CliContext {
@JsonProperty("locations") @JsonProperty("locations")
private Map<String, String> locations = new HashMap<String, String>(); private Map<String, String> locations = new HashMap<String, String>();
@JsonProperty("outputStyle")
private String outputStyle = null;
// TODO: Mark what goes here? // TODO: Mark what goes here?
private List<BundleValidationRule> bundleValidationRules = new ArrayList<>(); private List<BundleValidationRule> bundleValidationRules = new ArrayList<>();
@ -517,6 +520,14 @@ public class CliContext {
this.showTimes = showTimes; this.showTimes = showTimes;
} }
public String getOutputStyle() {
return outputStyle;
}
public void setOutputStyle(String outputStyle) {
this.outputStyle = outputStyle;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -553,12 +564,13 @@ public class CliContext {
Objects.equals(showTimes, that.showTimes) && Objects.equals(showTimes, that.showTimes) &&
mode == that.mode && mode == that.mode &&
Objects.equals(locale, that.locale) && Objects.equals(locale, that.locale) &&
Objects.equals(outputStyle, that.outputStyle) &&
Objects.equals(locations, that.locations); Objects.equals(locations, that.locations);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes, allowExampleUrls); return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes, allowExampleUrls, outputStyle);
} }
@Override @Override
@ -593,6 +605,7 @@ public class CliContext {
", mode=" + mode + ", mode=" + mode +
", securityChecks=" + securityChecks + ", securityChecks=" + securityChecks +
", crumbTrails=" + crumbTrails + ", crumbTrails=" + crumbTrails +
", outputStyle=" + outputStyle +
", allowExampleUrls=" + allowExampleUrls + ", allowExampleUrls=" + allowExampleUrls +
", showTimes=" + showTimes + ", showTimes=" + showTimes +
", locale='" + locale + '\'' + ", locale='" + locale + '\'' +

View File

@ -0,0 +1,72 @@
package org.hl7.fhir.validation.cli.renderers;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
public class DefaultRenderer extends ValidationOutputRenderer {
@Override
public void render(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++;
}
if (moreThanOne) {
System.out.print("-- ");
System.out.print(file);
System.out.print(" --");
System.out.println(Utilities.padLeft("", '-', Integer.max(38, file.length() + 6)));
}
System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes");
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
System.out.println(getIssueSummary(issue));
ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg");
if (vm != null && vm.sliceText != null && (crumbTrails || vm.isCriticalSignpost())) {
for (String s : vm.sliceText) {
System.out.println(" slice info: "+s);
}
}
}
if (moreThanOne) {
System.out.print("---");
System.out.print(Utilities.padLeft("", '-', file.length()));
System.out.print("---");
System.out.println(Utilities.padLeft("", '-', Integer.max(38, file.length() + 6)));
System.out.println();
}
}
private String getIssueSummary(OperationOutcome.OperationOutcomeIssueComponent issue) {
String loc;
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);
if (issue.getSeverity() == IssueSeverity.INFORMATION && (line == -1 || col == -1)) {
loc = "";
} else {
loc = " @ "+"line " + Integer.toString(line) + ", col" + Integer.toString(col);
}
}
return " " + issue.getSeverity().getDisplay() + loc + ": " + issue.getDetails().getText();
}
}

View File

@ -0,0 +1,18 @@
package org.hl7.fhir.validation.cli.renderers;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
public class ESLintCompactRenderer extends ValidationOutputRenderer {
@Override
public void render(OperationOutcome oo) {
String file = ToolingExtensions.readStringExtension(oo, ToolingExtensions.EXT_OO_FILE);
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1);
int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1);
System.out.println(file+": line " + Integer.toString(line) + ", col" + Integer.toString(col)+", "+issue.getSeverity().getDisplay()+" - "+issue.getDetails().getText());
}
}
}

View File

@ -0,0 +1,27 @@
package org.hl7.fhir.validation.cli.renderers;
import org.hl7.fhir.r5.model.OperationOutcome;
public abstract class ValidationOutputRenderer {
protected boolean crumbTrails;
protected boolean moreThanOne;
public boolean isCrumbTrails() {
return crumbTrails;
}
public void setCrumbTrails(boolean crumbTrails) {
this.crumbTrails = crumbTrails;
}
public void start(boolean moreThanOne) {
this.moreThanOne = moreThanOne;
}
public abstract void render(OperationOutcome op);
public void finish() {
}
}

View File

@ -26,6 +26,9 @@ import org.hl7.fhir.validation.IgLoader;
import org.hl7.fhir.validation.ValidationEngine; import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.ValidationRecord; import org.hl7.fhir.validation.ValidationRecord;
import org.hl7.fhir.validation.cli.model.*; import org.hl7.fhir.validation.cli.model.*;
import org.hl7.fhir.validation.cli.renderers.DefaultRenderer;
import org.hl7.fhir.validation.cli.renderers.ESLintCompactRenderer;
import org.hl7.fhir.validation.cli.renderers.ValidationOutputRenderer;
import org.hl7.fhir.validation.cli.utils.EngineMode; import org.hl7.fhir.validation.cli.utils.EngineMode;
import org.hl7.fhir.validation.cli.utils.VersionSourceInformation; import org.hl7.fhir.validation.cli.utils.VersionSourceInformation;
@ -96,20 +99,32 @@ public class ValidationService {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
List<ValidationRecord> records = new ArrayList<>(); List<ValidationRecord> records = new ArrayList<>();
Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles(), records); Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles(), records);
int ec = 0;
MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
System.out.println("Done. " + validator.getContext().clock().report()+". Memory = "+Utilities.describeSize(mbean.getHeapMemoryUsage().getUsed()+mbean.getNonHeapMemoryUsage().getUsed())); System.out.println("Done. " + validator.getContext().clock().report()+". Memory = "+Utilities.describeSize(mbean.getHeapMemoryUsage().getUsed()+mbean.getNonHeapMemoryUsage().getUsed()));
System.out.println(); System.out.println();
ValidationOutputRenderer renderer = makeValidationOutputRenderer(cliContext);
renderer.setCrumbTrails(validator.isCrumbTrails());
int ec = 0;
if (cliContext.getOutput() == null) { if (cliContext.getOutput() == null) {
if (r instanceof Bundle) if (r instanceof Bundle) {
for (Bundle.BundleEntryComponent e : ((Bundle) r).getEntry()) renderer.start(((Bundle) r).getEntry().size() > 1);
ec = ec + displayOperationOutcome((OperationOutcome) e.getResource(), ((Bundle) r).getEntry().size() > 1, validator.isCrumbTrails()) + ec; for (Bundle.BundleEntryComponent e : ((Bundle) r).getEntry()) {
else if (r == null) { OperationOutcome op = (OperationOutcome) e.getResource();
ec = ec + countErrors(op);
renderer.render(op);
}
renderer.finish();
} else if (r == null) {
ec = ec + 1; ec = ec + 1;
System.out.println("No output from validation - nothing to validate"); System.out.println("No output from validation - nothing to validate");
} else { } else {
ec = displayOperationOutcome((OperationOutcome) r, false, validator.isCrumbTrails()); renderer.start(false);
OperationOutcome op = (OperationOutcome) r;
ec = countErrors(op);
renderer.render((OperationOutcome) r);
renderer.finish();
} }
} else { } else {
IParser x; IParser x;
@ -131,6 +146,30 @@ public class ValidationService {
System.exit(ec > 0 ? 1 : 0); System.exit(ec > 0 ? 1 : 0);
} }
private int countErrors(OperationOutcome oo) {
int error = 0;
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
if (issue.getSeverity() == OperationOutcome.IssueSeverity.FATAL || issue.getSeverity() == OperationOutcome.IssueSeverity.ERROR)
error++;
}
return error;
}
private ValidationOutputRenderer makeValidationOutputRenderer(CliContext cliContext) {
String style = cliContext.getOutputStyle();
// adding to this list?
// Must document the option at https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator#UsingtheFHIRValidator-ManagingOutput
// if you're going to make a PR, document the link where the outputstyle is documented, along with a sentence that describes it, in the PR notes
if (Utilities.noString(style)) {
return new DefaultRenderer();
} else if (Utilities.existsInList(style, "eslint-compact")) {
return new ESLintCompactRenderer();
} else {
System.out.println("Unknown output style '"+style+"'");
return new DefaultRenderer();
}
}
public void convertSources(CliContext cliContext, ValidationEngine validator) throws Exception { public void convertSources(CliContext cliContext, ValidationEngine validator) throws Exception {
System.out.println(" ...convert"); System.out.println(" ...convert");
validator.convert(cliContext.getSources().get(0), cliContext.getOutput()); validator.convert(cliContext.getSources().get(0), cliContext.getOutput());
@ -270,67 +309,6 @@ public class ValidationService {
return sessionId; return sessionId;
} }
public int displayOperationOutcome(OperationOutcome oo, boolean hasMultiples, boolean crumbs) {
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++;
}
if (hasMultiples) {
System.out.print("-- ");
System.out.print(file);
System.out.print(" --");
System.out.println(Utilities.padLeft("", '-', Integer.max(38, file.length() + 6)));
}
System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes");
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
System.out.println(getIssueSummary(issue));
ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg");
if (vm != null && vm.sliceText != null && (crumbs || vm.isCriticalSignpost())) {
for (String s : vm.sliceText) {
System.out.println(" slice info: "+s);
}
}
}
if (hasMultiples) {
System.out.print("---");
System.out.print(Utilities.padLeft("", '-', file.length()));
System.out.print("---");
System.out.println(Utilities.padLeft("", '-', Integer.max(38, file.length() + 6)));
System.out.println();
}
return error;
}
private String getIssueSummary(OperationOutcome.OperationOutcomeIssueComponent issue) {
String loc;
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);
if (issue.getSeverity() == IssueSeverity.INFORMATION && (line == -1 || col == -1)) {
loc = "";
} else {
loc = " @ "+(line >= 0 && col >= 0 ? "line " + Integer.toString(line) + ", col" + Integer.toString(col) : "??");
}
}
return " " + issue.getSeverity().getDisplay() + loc + ": " + issue.getDetails().getText();
}
public String determineVersion(CliContext cliContext) throws Exception { public String determineVersion(CliContext cliContext) throws Exception {
return determineVersion(cliContext, null); return determineVersion(cliContext, null);
} }

View File

@ -61,6 +61,7 @@ public class Params {
public static final String VERBOSE = "-verbose"; public static final String VERBOSE = "-verbose";
public static final String SHOW_TIMES = "-show-times"; public static final String SHOW_TIMES = "-show-times";
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls"; public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
public static final String OUTPUT_STYLE = "-output-style";
/** /**
* Checks the list of passed in params to see if it contains the passed in param. * Checks the list of passed in params to see if it contains the passed in param.
@ -203,6 +204,8 @@ public class Params {
} }
} else if (args[i].equals(SHOW_TIMES)) { } else if (args[i].equals(SHOW_TIMES)) {
cliContext.setShowTimes(true); cliContext.setShowTimes(true);
} else if (args[i].equals(OUTPUT_STYLE)) {
cliContext.setOutputStyle(args[++i]);
} else if (args[i].equals(SCAN)) { } else if (args[i].equals(SCAN)) {
cliContext.setMode(EngineMode.SCAN); cliContext.setMode(EngineMode.SCAN);
} else if (args[i].equals(TERMINOLOGY)) { } else if (args[i].equals(TERMINOLOGY)) {