From 6fe16d181217b689377bc18eebca9daadc8b1f9d Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 6 Mar 2023 20:44:17 +1100 Subject: [PATCH 1/4] fix bug parsing parameters in FML --- .../org/hl7/fhir/r5/elementmodel/FmlParser.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java index 1b9779542..a0716a98e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java @@ -111,12 +111,12 @@ public class FmlParser extends ParserBase { lexer.token("conceptmap"); Element map = structureMap.makeElement("contained"); StructureDefinition sd = context.fetchTypeDefinition("ConceptMap"); - map.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(map.getProperty()), map.getProperty()); + map.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(map.getElementProperty() != null ? map.getElementProperty() : map.getProperty()), map.getProperty()); map.setType("ConceptMap"); Element eid = map.makeElement("id").markLocation(lexer.getCurrentLocation()); String id = lexer.readConstant("map id"); if (id.startsWith("#")) - throw lexer.error("Concept Map identifier must start with #"); + throw lexer.error("Concept Map identifier must not start with #"); eid.setValue(id); map.makeElement("status").setValue(structureMap.getChildValue("status")); lexer.token("{"); @@ -363,8 +363,8 @@ public class FmlParser extends ParserBase { rule.forceElement("target").makeElement("transform").setValue(StructureMapTransform.CREATE.toCode()); Element dep = rule.forceElement("dependent"); dep.makeElement("name").setValue(StructureMapUtilities.DEF_GROUP_NAME); - dep.makeElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME); - dep.makeElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME); + dep.addElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME); + dep.addElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME); // no dependencies - imply what is to be done based on types } if (newFmt) { @@ -502,7 +502,7 @@ public class FmlParser extends ParserBase { loc = lexer.getCurrentLocation(); ExpressionNode node = fpe.parse(lexer); target.setUserData(StructureMapUtilities.MAP_EXPRESSION, node); - target.addElement("parameter").markLocation(loc).setValue(node.toString()); + target.addElement("parameter").markLocation(loc).makeElement("valueString").setValue(node.toString()); } else { while (!lexer.hasToken(")")) { parseParameter(target, lexer); @@ -519,9 +519,9 @@ public class FmlParser extends ParserBase { while (lexer.hasToken(".")) { id = id + lexer.take() + lexer.take(); } - target.addElement("parameter").markLocation(loc).setValue(id); + target.addElement("parameter").markLocation(loc).makeElement("valueId").setValue(id); } else { - target.addElement("parameter").markLocation(lexer.getCurrentLocation()).setValue(readConstant(name, lexer)); + target.addElement("parameter").markLocation(lexer.getCurrentLocation()).makeElement("valueString").setValue(readConstant(name, lexer)); } } if (lexer.hasToken("as")) { From 507ff74c2398ee1350b1033f5a899c71c516205f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 6 Mar 2023 20:44:41 +1100 Subject: [PATCH 2/4] recognise R4B and R5 core packages --- .../src/main/java/org/hl7/fhir/utilities/VersionUtilities.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java index c61ffcb98..c16169c48 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java @@ -197,7 +197,7 @@ public class VersionUtilities { if (s.contains("#")) { s = s.substring(0, s.indexOf("#")); } - return Utilities.existsInList(s, "hl7.fhir.core","hl7.fhir.r2.core", "hl7.fhir.r2b.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core"); + return Utilities.existsInList(s, "hl7.fhir.core","hl7.fhir.r2.core", "hl7.fhir.r2b.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r4b.core", "hl7.fhir.r5.core"); } public static String getMajMin(String version) { From 6559c4b245c55eeadeaba63864f4e59c574a50ac Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 6 Mar 2023 20:45:05 +1100 Subject: [PATCH 3/4] improve SM validation message --- org.hl7.fhir.utilities/src/main/resources/Messages.properties | 2 +- .../fhir/validation/instance/type/StructureMapValidator.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index cf774ee0d..fe96be755 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -857,7 +857,7 @@ SM_TARGET_TRANSFORM_PARAM_COUNT_RANGE = Transform {0} takes {1}-{2} parameter(s) SM_TARGET_TRANSFORM_PARAM_COUNT_SINGLE = Transform {0} takes {1} parameter(s) but {2} were found SM_TARGET_TRANSFORM_NOT_CHECKED = Transform {0} not checked dyet SM_TARGET_NO_TRANSFORM_NO_CHECKED = When there is no transform, parameters can''t be provided -SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE = The value of the type parameter could not be processed +SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE = The value of the type parameter for {0} could not be processed SM_TARGET_TRANSFORM_PARAM_UNPROCESSIBLE = The parameter at index {0} could not be processed (type = {1}) SM_TARGET_TRANSFORM_EXPRESSION_ERROR = The FHIRPath expression passed as the evaluate parameter is invalid: {0} SM_IMPORT_NOT_FOUND = No maps were found to match {0} - validation may be wrong diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java index 343b797e1..89f5f0a51 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java @@ -633,7 +633,7 @@ public class StructureMapValidator extends BaseValidator { if (rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), params.size() < 2, I18nConstants.SM_TARGET_TRANSFORM_PARAM_COUNT_RANGE, "create", "0", "1", params.size())) { if (params.size() == 1) { type = params.get(0).getChildValue("value"); - warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(),type != null, I18nConstants.SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE); + warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(),type != null, I18nConstants.SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE, "create"); } else { // maybe can guess? maybe not ... type = } @@ -645,7 +645,7 @@ public class StructureMapValidator extends BaseValidator { if (rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), params.size() < 2, I18nConstants.SM_TARGET_TRANSFORM_PARAM_COUNT_RANGE, "create", "0", "1", params.size())) { if (params.size() == 1) { type = params.get(0).getChildValue("value"); - warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(),type != null, I18nConstants.SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE); + warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(),type != null, I18nConstants.SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE, "copy"); } else { // maybe can guess? maybe not ... type = } From e449bf9cfed9bb8b72463851dac8cd41a2a4e306 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 6 Mar 2023 20:45:21 +1100 Subject: [PATCH 4/4] Add compact rendering --- .../validation/cli/renderers/CSVRenderer.java | 19 +++++ .../cli/renderers/CompactRenderer.java | 71 +++++++++++++++++++ .../cli/renderers/DefaultRenderer.java | 19 +++++ .../cli/renderers/ESLintCompactRenderer.java | 19 +++++ .../cli/renderers/NativeRenderer.java | 17 +++++ .../renderers/ValidationOutputRenderer.java | 7 ++ .../cli/services/ValidationService.java | 29 +++++--- 7 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CompactRenderer.java diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CSVRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CSVRenderer.java index 850eea555..dff3fbc20 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CSVRenderer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CSVRenderer.java @@ -1,5 +1,7 @@ package org.hl7.fhir.validation.cli.renderers; +import java.io.File; + import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; @@ -21,4 +23,21 @@ public class CSVRenderer extends ValidationOutputRenderer { } } + + @Override + public boolean isSingleFile() { + return true; + } + + @Override + public String getStyleCode() { + return "csv"; + } + + @Override + public void setFolder(File dir) { + throw new Error("Not supported"); + + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CompactRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CompactRenderer.java new file mode 100644 index 000000000..62ec2800b --- /dev/null +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/CompactRenderer.java @@ -0,0 +1,71 @@ +package org.hl7.fhir.validation.cli.renderers; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hl7.fhir.r5.model.OperationOutcome; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.Utilities; + +public class CompactRenderer extends ValidationOutputRenderer { + + private boolean split; + private File dir; + + public CompactRenderer(boolean split) { + super(); + this.split = split; + } + + @Override + public void render(OperationOutcome op) throws IOException { + if (split) { + String file = Utilities.changeFileExt(tail(ToolingExtensions.readStringExtension(op, ToolingExtensions.EXT_OO_FILE)), ".txt"); + PrintStream dstF = new PrintStream(new FileOutputStream(Utilities.path(dir.getAbsolutePath(), file))); + render(dstF, op); + dstF.close(); + } else { + render(dst, op); + } + } + + private void render(PrintStream d, OperationOutcome op) { + d.println(ToolingExtensions.readStringExtension(op, ToolingExtensions.EXT_OO_FILE)); + List lines = new ArrayList<>(); + for (OperationOutcome.OperationOutcomeIssueComponent issue : op.getIssue()) { + String path = issue.hasExpression() ? issue.getExpression().get(0).asStringValue() : "n/a"; + int line = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, -1); + int col = ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, -1); + lines.add("["+Integer.toString(line) + ", " + Integer.toString(col)+"] "+path+": "+issue.getSeverity().getDisplay()+" - "+issue.getDetails().getText()); + } + Collections.sort(lines); + for (String s : lines) { + d.println(s); + } + } + + private String tail(String n) { + return n.contains(File.separator) ? n.substring(n.lastIndexOf(File.separator)+1) : n; + } + + @Override + public boolean isSingleFile() { + return !split; + } + + @Override + public String getStyleCode() { + return split ? "compact-split" : "compact"; + } + + @Override + public void setFolder(File dir) { + this.dir = dir; + } + +} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/DefaultRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/DefaultRenderer.java index 08d93adfc..941e2423a 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/DefaultRenderer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/DefaultRenderer.java @@ -1,5 +1,7 @@ package org.hl7.fhir.validation.cli.renderers; +import java.io.File; + import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity; import org.hl7.fhir.r5.utils.ToolingExtensions; @@ -69,4 +71,21 @@ public class DefaultRenderer extends ValidationOutputRenderer { return " " + issue.getSeverity().getDisplay() + loc + ": " + issue.getDetails().getText(); } + + @Override + public boolean isSingleFile() { + return true; + } + + @Override + public String getStyleCode() { + return "(default)"; + } + + @Override + public void setFolder(File dir) { + throw new Error("Not supported"); + + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ESLintCompactRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ESLintCompactRenderer.java index 88bc2ee51..436608c42 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ESLintCompactRenderer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ESLintCompactRenderer.java @@ -1,5 +1,7 @@ package org.hl7.fhir.validation.cli.renderers; +import java.io.File; + import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; @@ -15,4 +17,21 @@ public class ESLintCompactRenderer extends ValidationOutputRenderer { } } + + @Override + public boolean isSingleFile() { + return true; + } + + @Override + public String getStyleCode() { + return "eslint-compact"; + } + + @Override + public void setFolder(File dir) { + throw new Error("Not supported"); + + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/NativeRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/NativeRenderer.java index d8a41290c..e2520481e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/NativeRenderer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/NativeRenderer.java @@ -1,5 +1,6 @@ package org.hl7.fhir.validation.cli.renderers; +import java.io.File; import java.io.IOException; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; @@ -44,5 +45,21 @@ public class NativeRenderer extends ValidationOutputRenderer { x.setOutputStyle(IParser.OutputStyle.PRETTY); x.compose(dst, bundle); } + + @Override + public boolean isSingleFile() { + return true; + } + + @Override + public String getStyleCode() { + return format.toString().toLowerCase(); + } + + @Override + public void setFolder(File dir) { + throw new Error("Not supported"); + + } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ValidationOutputRenderer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ValidationOutputRenderer.java index f623c156b..28a13d2bf 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ValidationOutputRenderer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/renderers/ValidationOutputRenderer.java @@ -1,5 +1,6 @@ package org.hl7.fhir.validation.cli.renderers; +import java.io.File; import java.io.IOException; import java.io.PrintStream; @@ -40,4 +41,10 @@ public abstract class ValidationOutputRenderer { public boolean handlesBundleDirectly() { return false; } + + public abstract boolean isSingleFile(); + + public abstract String getStyleCode(); + + public abstract void setFolder(File dir); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java index 47c16604a..4fb82affb 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java @@ -1,5 +1,6 @@ package org.hl7.fhir.validation.cli.services; +import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; @@ -47,6 +48,7 @@ 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.renderers.CSVRenderer; +import org.hl7.fhir.validation.cli.renderers.CompactRenderer; import org.hl7.fhir.validation.cli.renderers.DefaultRenderer; import org.hl7.fhir.validation.cli.renderers.ESLintCompactRenderer; import org.hl7.fhir.validation.cli.renderers.NativeRenderer; @@ -119,15 +121,22 @@ public class ValidationService { System.out.println(); PrintStream dst = null; - if (cliContext.getOutput() == null) { - dst = System.out; - } else { - dst = new PrintStream(new FileOutputStream(cliContext.getOutput())); - } - ValidationOutputRenderer renderer = makeValidationOutputRenderer(cliContext); - renderer.setOutput(dst); renderer.setCrumbTrails(validator.isCrumbTrails()); + if (renderer.isSingleFile()) { + if (cliContext.getOutput() == null) { + dst = System.out; + } else { + dst = new PrintStream(new FileOutputStream(cliContext.getOutput())); + } + renderer.setOutput(dst); + } else { + File dir = new File(cliContext.getOutput()); + if (!dir.isDirectory()) { + throw new Error("THe output location "+dir.getAbsolutePath()+" must be a directory for the output style "+renderer.getStyleCode()); + } + renderer.setFolder(dir); + } int ec = 0; @@ -154,7 +163,7 @@ public class ValidationService { renderer.finish(); } - if (cliContext.getOutput() != null) { + if (cliContext.getOutput() != null && dst != null) { dst.close(); } @@ -190,6 +199,10 @@ public class ValidationService { } } else if (Utilities.existsInList(style, "eslint-compact")) { return new ESLintCompactRenderer(); + } else if (Utilities.existsInList(style, "compact-split")) { + return new CompactRenderer(true); + } else if (Utilities.existsInList(style, "compact")) { + return new CompactRenderer(false); } else if (Utilities.existsInList(style, "csv")) { return new CSVRenderer(); } else if (Utilities.existsInList(style, "xml")) {