diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/analytics/PackageVisitor.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/analytics/PackageVisitor.java index 3b29a673f..2adb4ec2a 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/analytics/PackageVisitor.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/analytics/PackageVisitor.java @@ -155,7 +155,7 @@ public class PackageVisitor { System.out.println("Go: "+cpidMap.size()+" current packages"); int i = 0; for (String s : cpidMap.keySet()) { - processCurrentPackage(s, cpidMap.get(s), cpidSet, i, cpidMap.size()); + processCurrentPackage(cpidMap.get(s), s, cpidSet, i, cpidMap.size()); i++; } @@ -266,12 +266,20 @@ public class PackageVisitor { } private Map getAllCIPackages() throws IOException { + System.out.println("Fetch https://build.fhir.org/ig/qas.json"); Map res = new HashMap<>(); if (current) { JsonArray json = (JsonArray) JsonParser.parseFromUrl("https://build.fhir.org/ig/qas.json"); for (JsonObject o : json.asJsonObjects()) { String url = o.asString("repo"); - res.put(url, o.asString("package-id")); + String pid = o.asString("package-id"); + if (url.contains("/branches/master") || url.contains("/branches/main") ) { + if (!res.containsKey(pid)) { + res.put(pid, url); + } else if (!url.equals(res.get(pid))) { + System.out.println("Ignore "+url+" already encountered "+pid +" @ "+res.get(pid)); + } + } } } return res; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java index 254b09ba5..71963825a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java @@ -308,4 +308,9 @@ public class ComparisonRenderer implements IEvaluationContext { return null; } + @Override + public boolean paramIsType(String name, int index) { + return false; + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index 9d0cae21b..bc73c401f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -132,6 +132,7 @@ public class Element extends Base implements NamedItem { private Base source; private boolean ignorePropertyOrder; private FhirFormat format; + private Object nativeObject; public Element(String name) { super(); @@ -1478,4 +1479,13 @@ public class Element extends Base implements NamedItem { return this; } + public Object getNativeObject() { + return nativeObject; + } + + public Element setNativeObject(Object nativeObject) { + this.nativeObject = nativeObject; + return this; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java index 8e0d95951..de0a60e5b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java @@ -193,6 +193,7 @@ public class JsonParser extends ParserBase { } private void checkObject(List errors, JsonObject object, Element b, String path) { + b.setNativeObject(object); checkComments(errors, object, b, path); if (policy == ValidationPolicy.EVERYTHING) { if (object.getProperties().size() == 0) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java index 8571304d8..14e5e8061 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java @@ -224,6 +224,12 @@ public abstract class ParserBase { new ContextUtilities(context).generateSnapshot(sd); return sd; } + } + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { + if (name.equals(sd.getUrl()) && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { + new ContextUtilities(context).generateSnapshot(sd); + return sd; + } } logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); return null; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java index d2fbcdd30..34336835f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java @@ -302,7 +302,7 @@ public class XmlParser extends ParserBase { public Element parse(List errors, org.w3c.dom.Element base, String type) throws Exception { StructureDefinition sd = getDefinition(errors, 0, 0, FormatUtilities.FHIR_NS, type); - Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd)).setFormat(FhirFormat.XML); + Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd)).setFormat(FhirFormat.XML).setNativeObject(base); result.setPath(base.getLocalName()); String path = "/"+pathPrefix(base.getNamespaceURI())+base.getLocalName(); checkElement(errors, base, path, result.getProperty(), false); @@ -431,7 +431,7 @@ public class XmlParser extends ParserBase { } } } - Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML); + Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML).setNativeObject(child); n.setPath(element.getPath()+"."+property.getName()); element.getChildren().add(n); } else { @@ -440,7 +440,7 @@ public class XmlParser extends ParserBase { if (!property.isChoice() && !name.equals(property.getName())) { name = property.getName(); } - Element n = new Element(name, property).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML); + Element n = new Element(name, property).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML).setNativeObject(child); if (property.isList()) { n.setPath(element.getPath()+"."+property.getName()+"["+repeatCount+"]"); } else { @@ -497,7 +497,7 @@ public class XmlParser extends ParserBase { npath = npath+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName(); name = child.getLocalName(); - Element n = new Element(name, property).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML); + Element n = new Element(name, property).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML).setNativeObject(child); cgn.getChildren().add(n); n.setPath(element.getPath()+"."+property.getName()); checkElement(errors, (org.w3c.dom.Element) child, npath, n.getProperty(), false); @@ -524,7 +524,7 @@ public class XmlParser extends ParserBase { npath = npath+"/text()"; name = mtProp.getName(); - Element n = new Element(name, mtProp, mtProp.getType(), child.getTextContent().trim()).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML); + Element n = new Element(name, mtProp, mtProp.getType(), child.getTextContent().trim()).markLocation(line(child, false), col(child, false)).setFormat(FhirFormat.XML).setNativeObject(child); cgn.getChildren().add(n); n.setPath(element.getPath()+"."+mtProp.getName()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index 7b8a4a658..a7383ff93 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -1518,6 +1518,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } c.addPiece(gen.new Piece(null, "Instances of this logical model cannot be the target of a Reference", null).addStyle("font-weight:bold")); } + String ps = ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_PROFILE_STYLE); + if (ps != null) { + if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } + if ("cda".equals(ps)) { + c.addPiece(gen.new Piece(null, "Instances of this type are validated by templateId", null).addStyle("font-weight:bold")); + } else { + c.addPiece(gen.new Piece(null, "Instances of this type are validated using an unknown approach: "+ps, null).addStyle("font-weight:bold")); + } + } } } if (definition != null) { @@ -3564,6 +3573,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } else { tableRow(tbl, "Logical Model", null, strikethrough, "Instances of this logical model cannot be the target of a Reference"); } + String ps = ToolingExtensions.readStringExtension(sd, ToolingExtensions.EXT_PROFILE_STYLE); + if (ps != null) { + if ("cda".equals(ps)) { + tableRow(tbl, "Validation", null, strikethrough, "Instances of this type are validated by templateId"); + } else { + tableRow(tbl, "Validation", null, strikethrough, "Instances of this type are validated using an unknown approach: "+ps); + } + } } if (root && sd.hasExtension(ToolingExtensions.EXT_SD_IMPOSE_PROFILE)) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/providers/URICodeSystem.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/providers/URICodeSystem.java index 8deb9897e..3b57c6e83 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/providers/URICodeSystem.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/providers/URICodeSystem.java @@ -9,7 +9,7 @@ public class URICodeSystem extends SpecialCodeSystem { @Override public ConceptDefinitionComponent findConcept(Coding code) { if (Utilities.isAbsoluteUrl(code.getCode())) { - return new ConceptDefinitionComponent(code.getCode()); + return new ConceptDefinitionComponent(code.getCode()).setDisplay(code.hasDisplay() ? code.getDisplay() : code.getCode()); } else { return null; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java index 24f29a319..207f0e261 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java @@ -1265,7 +1265,9 @@ public class ValueSetValidator extends ValueSetProcessBase { public boolean validateCodeInConceptList(String code, CodeSystem def, List list, AlternateCodesProcessingRules altCodeRules) { opContext.deadCheck(); - if (def.getCaseSensitive()) { + if (def.hasUserData("tx.cs.special")) { + return ((SpecialCodeSystem) def.getUserData("tx.cs.special")).findConcept(new Coding().setCode(code)) != null; + } else if (def.getCaseSensitive()) { for (ConceptDefinitionComponent cc : list) { if (cc.getCode().equals(code)) { return true; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index e549e4bf2..5def56759 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -33,6 +33,7 @@ import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.BaseDateTimeType; import org.hl7.fhir.r5.model.BooleanType; import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CodeType; import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.DateTimeType; @@ -203,6 +204,13 @@ public class FHIRPathEngine { * return the value set referenced by the url, which has been used in memberOf() */ public ValueSet resolveValueSet(Object appContext, String url); + + /** + * For the moment, there can only be one parameter if it's a type parameter + * @param name + * @return true if it's a type parameter + */ + public boolean paramIsType(String name, int index); } /** @@ -3162,7 +3170,7 @@ public class FHIRPathEngine { @SuppressWarnings("unchecked") private TypeDetails evaluateFunctionType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, Set elementDependencies, ExpressionNode container) throws PathEngineException, DefinitionException { List paramTypes = new ArrayList(); - if (exp.getFunction() == Function.Is || exp.getFunction() == Function.As || exp.getFunction() == Function.OfType) { + if (exp.getFunction() == Function.Is || exp.getFunction() == Function.As || exp.getFunction() == Function.OfType || (exp.getFunction() == Function.Custom && hostServices.paramIsType(exp.getName(), 0))) { paramTypes.add(new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String)); } else if (exp.getFunction() == Function.Repeat && exp.getParameters().size() == 1) { TypeDetails base = TypeDetails.empty(); @@ -3793,8 +3801,22 @@ public class FHIRPathEngine { case Custom: { List> params = new ArrayList>(); - for (ExpressionNode p : exp.getParameters()) { - params.add(execute(context, focus, p, true)); + if (hostServices.paramIsType( exp.getName(), 0)) { + if (exp.getParameters().size() > 0) { + String tn; + if (exp.getParameters().get(0).getInner() != null) { + tn = exp.getParameters().get(0).getName()+"."+exp.getParameters().get(0).getInner().getName(); + } else { + tn = "FHIR."+exp.getParameters().get(0).getName(); + } + List p = new ArrayList<>(); + p.add(new CodeType(tn)); + params.add(p); + } + } else { + for (ExpressionNode p : exp.getParameters()) { + params.add(execute(context, focus, p, true)); + } } return hostServices.executeFunction(context.appInfo, focus, exp.getName(), params); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java index 9a0e259d1..32ba081b9 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java @@ -853,4 +853,8 @@ public class LiquidEngine implements IEvaluationContext { return replaced; } + @Override + public boolean paramIsType(String name, int index) { + return false; + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java index 07825fdcb..126d4cfb8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java @@ -257,6 +257,7 @@ public class ToolingExtensions { public static final String EXT_NO_BINDING = "http://hl7.org/fhir/tools/StructureDefinition/no-binding"; public static final String EXT_ID_CHOICE_GROUP = "http://hl7.org/fhir/tools/StructureDefinition/xml-choice-group"; public static final String EXT_DATE_RULES = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-rules"; + public static final String EXT_PROFILE_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/type-profile-style"; // specific extension helpers diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java index 3ca7c9be9..4c293d895 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java @@ -111,7 +111,11 @@ public class Runner implements IEvaluationContext { } if (ok) { List> rows = new ArrayList<>(); - generateCells(b, vd, rows); + rows.add(new ArrayList()); + + for (JsonObject select : vd.getJsonObjects("select")) { + executeSelect(select, b, rows); + } for (List row : rows) { storage.addRow(store, row); } @@ -119,48 +123,47 @@ public class Runner implements IEvaluationContext { } storage.finish(store); } - - private void generateCells(Base bl, JsonObject vd, List> rows) { - if (vd.has("forEach")) { - executeForEach(vd, bl, rows); - } else if (vd.has("forEachOrNull")) { - executeForEachOrNull(vd, bl, rows); - } else if (vd.has("union")) { - executeUnion(vd, bl, rows); - } else { - for (JsonObject select : vd.getJsonObjects("select")) { - executeSelect(select, bl, rows); - } - } - } - private void executeSelect(JsonObject select, Base bl, List> rows) { - if (select.has("path")) { - executeSelectPath(select, bl, rows); - } else if (select.has("forEach")) { - executeForEach(select, bl, rows); + private void executeSelect(JsonObject select, Base b, List> rows) { + List focus = new ArrayList<>(); + + if (select.has("forEach")) { + focus.addAll(executeForEach(select, b)); } else if (select.has("forEachOrNull")) { - executeForEachOrNull(select, bl, rows); - } else if (select.has("union")) { - executeUnion(select, bl, rows); + focus.addAll(executeForEachOrNull(select, b)); + } else { + focus.add(b); } - } - private void executeForEach(JsonObject focus, Base b, List> rows) { - ExpressionNode n = (ExpressionNode) focus.getUserData("forEach"); - List bl2 = fpe.evaluate(b, n); +// } else if (select.has("union")) { +// focus.addAll(executeUnion(select, b)); + List> tempRows = new ArrayList<>(); tempRows.addAll(rows); rows.clear(); - for (Base b2 : bl2) { - List> rowsToAdd = cloneRows(tempRows); - for (JsonObject select : focus.getJsonObjects("select")) { - executeSelect(select, b2, rowsToAdd); + + for (Base f : focus) { + List> rowsToAdd = cloneRows(tempRows); + + for (JsonObject column : select.getJsonObjects("column")) { + executeColumn(column, f, rowsToAdd); + } + + for (JsonObject sub : select.getJsonObjects("union")) { + executeSelect(sub, f, rowsToAdd); + } + + for (JsonObject sub : select.getJsonObjects("select")) { + executeSelect(sub, f, rowsToAdd); } rows.addAll(rowsToAdd); } } + private List executeUnion(JsonObject focus, Base b, List> rows) { + throw new FHIRException("union is not supported"); + } + private List> cloneRows(List> rows) { List> list = new ArrayList<>(); for (List row : rows) { @@ -176,30 +179,38 @@ public class Runner implements IEvaluationContext { } return list; } - - private void executeForEachOrNull(JsonObject focus, Base b, List> rows) { - throw new FHIRException("forEachOrNull is not supported"); + + private List executeForEach(JsonObject focus, Base b) { + ExpressionNode n = (ExpressionNode) focus.getUserData("forEach"); + List result = new ArrayList<>(); + result.addAll(fpe.evaluate(b, n)); + return result; } - private void executeUnion(JsonObject focus, Base b, List> rows) { - throw new FHIRException("union is not supported"); + private List executeForEachOrNull(JsonObject focus, Base b) { + ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull"); + List result = new ArrayList<>(); + result.addAll(fpe.evaluate(b, n)); + if (result.size() == 0) { + result.add(null); + } + return result; } - - private void executeSelectPath(JsonObject select, Base b, List> rows) { - ExpressionNode n = (ExpressionNode) select.getUserData("path"); - List bl2 = fpe.evaluate(b, n); - String name = select.getUserString("name"); - if (!bl2.isEmpty()) { - if (rows.isEmpty()) { - rows.add(new ArrayList()); - } - for (List row : rows) { - Cell c = cell(row, name); - if (c == null) { - c = new Cell(column(name)); - row.add(c); - } + private void executeColumn(JsonObject column, Base b, List> rows) { + ExpressionNode n = (ExpressionNode) column.getUserData("path"); + List bl2 = new ArrayList<>(); + if (b != null) { + bl2.addAll(fpe.evaluate(b, n)); + } + String name = column.getUserString("name"); + for (List row : rows) { + Cell c = cell(row, name); + if (c == null) { + c = new Cell(column(name)); + row.add(c); + } + if (!bl2.isEmpty()) { if (bl2.size() + c.getValues().size() > 1) { // this is a problem if collection != true or if the storage can't deal with it // though this should've been picked up before now - but there are circumstances where it wouldn't be @@ -211,14 +222,6 @@ public class Runner implements IEvaluationContext { c.getValues().add(genValue(c.getColumn(), b2)); } } - } else { - for (List row : rows) { - Cell c = cell(row, name); - if (c == null) { - c = new Cell(column(name)); - row.add(c); - } - } } } @@ -376,6 +379,9 @@ public class Runner implements IEvaluationContext { String rt = null; if (parameters.size() > 0) { rt = parameters.get(0).get(0).primitiveValue(); + if (rt.startsWith("FHIR.")) { + rt = rt.substring(5); + } } List base = new ArrayList(); if (focus.size() == 1) { @@ -427,6 +433,10 @@ public class Runner implements IEvaluationContext { public ValueSet resolveValueSet(Object appContext, String url) { throw new Error("Not implemented yet: resolveValueSet"); } + @Override + public boolean paramIsType(String name, int index) { + return "getReferenceKey".equals(name); + } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java index 08ded3af0..aef51c783 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java @@ -1,6 +1,7 @@ package org.hl7.fhir.r5.utils.sql; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -24,20 +25,20 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.Source; public class Validator { - + private IWorkerContext context; private FHIRPathEngine fpe; private List prohibitedNames = new ArrayList(); private List issues = new ArrayList(); - private boolean arrays; - private boolean complexTypes; - private boolean needsName; + private Boolean arrays; + private Boolean complexTypes; + private Boolean needsName; private String resourceName; private List columns = new ArrayList(); private String name; - protected Validator(IWorkerContext context, FHIRPathEngine fpe, List prohibitedNames, boolean arrays, boolean complexTypes, boolean needsName) { + public Validator(IWorkerContext context, FHIRPathEngine fpe, List prohibitedNames, Boolean arrays, Boolean complexTypes, Boolean needsName) { super(); this.context = context; this.fpe = fpe; @@ -58,7 +59,9 @@ public class Validator { public void checkViewDefinition(String path, JsonObject viewDefinition) { JsonElement nameJ = viewDefinition.get("name"); if (nameJ == null) { - if (needsName) { + if (needsName == null) { + hint(path, viewDefinition, "No name provided. A name is required in many contexts where a ViewDefinition is used"); + } else if (needsName) { error(path, viewDefinition, "No name provided", IssueType.REQUIRED); } } else if (!(nameJ instanceof JsonString)) { @@ -122,119 +125,201 @@ public class Validator { } private void checkSelect(String path, JsonObject select, TypeDetails t) { - if (select.has("path")) { - checkSelectPath(path, select, select.get("path"), t); - } else if (select.has("forEach")) { - checkForEach(path, select, select.get("forEach"), t); + + if (select.has("forEach")) { + t = checkForEach(path, select, select.get("forEach"), t); } else if (select.has("forEachOrNull")) { - checkForEachOrNull(path, select, select.get("forEachOrNull"), t); - } else if (select.has("union")) { - checkUnion(path, select, select.get("union"), t); - } else { - error(path, select, "The select has neither a path, forEach, forEachOrNull, or union statement", IssueType.REQUIRED); + t = checkForEachOrNull(path, select, select.get("forEachOrNull"), t); + } + + if (t != null) { + boolean content = false; + + if (select.has("union")) { + content = checkUnion(path, select, select.get("union"), t); + } + + if (select.has("column")) { + JsonElement a = select.get("column"); + if (!(a instanceof JsonArray)) { + error(path+".column", a, "column is not an array", IssueType.INVALID); + } else { + content = true; + int i = 0; + for (JsonElement e : ((JsonArray) a)) { + if (!(e instanceof JsonObject)) { + error(path+".column["+i+"]", a, "column["+i+"] is a "+e.type().toName()+" not an object", IssueType.INVALID); + } else { + checkColumn(path+".column["+i+"]", (JsonObject) e, t); + } + } + } + } + + if (select.has("select")) { + JsonElement a = select.get("select"); + if (!(a instanceof JsonArray)) { + error(path+".select", a, "select is not an array", IssueType.INVALID); + } else { + content = true; + int i = 0; + for (JsonElement e : ((JsonArray) a)) { + if (!(e instanceof JsonObject)) { + error(path+".select["+i+"]", e, "select["+i+"] is not an object", IssueType.INVALID); + } else { + checkSelect(path+".select["+i+"]", (JsonObject) e, t); + } + } + } + } + + if (!content) { + error(path, select, "The select has no columns or selects", IssueType.REQUIRED); + } } } - private void checkSelectPath(String path, JsonObject select, JsonElement expression, TypeDetails t) { - if (!(expression instanceof JsonString)) { - error(path+".forEach", expression, "forEach is not a string", IssueType.INVALID); - } else { - String expr = expression.asString(); - List warnings = new ArrayList<>(); - TypeDetails td = null; - ExpressionNode node = null; - try { - node = fpe.parse(expr); - select.setUserData("path", node); - td = fpe.checkOnTypes(null, resourceName, t, node, warnings); - } catch (Exception e) { - error(path, expression, e.getMessage(), IssueType.INVALID); + private boolean checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + JsonElement a = focus.get("union"); + if (!(a instanceof JsonArray)) { + error(path+".union", a, "union is not an array", IssueType.INVALID); + return false; + } else { + int i = 0; + for (JsonElement e : ((JsonArray) a)) { + if (!(e instanceof JsonObject)) { + error(path+".union["+i+"]", e, "union["+i+"] is not an object", IssueType.INVALID); + } else { + checkSelect(path+".union["+i+"]", (JsonObject) e, t); + } + } + if (i < 2) { + warning(path+".union", a, "union should have more than one item"); } - if (td != null && node != null) { - for (String s : warnings) { - warning(path+".path", expression, s); - } - String columnName = null; - JsonElement aliasJ = select.get("alias"); - if (aliasJ != null) { - if (aliasJ instanceof JsonString) { - columnName = aliasJ.asString(); - if (!isValidName(columnName)) { - error(path+".name", aliasJ, "The name '"+columnName+"' is not valid", IssueType.VALUE); - } - } else { - error(path+".alias", aliasJ, "alias must be a string", IssueType.INVALID); - } - } - if (columnName == null) { - List names = node.getDistalNames(); - if (names.size() == 1 && names.get(0) != null) { - columnName = names.get(0); - if (!isValidName(columnName)) { - error(path+".path", expression, "The name '"+columnName+"' found in the path expression is not a valid column name, so an alias is required", IssueType.INVARIANT); - } - } else { - error(path, select, "The path does not resolve to a name, so an alias is required", IssueType.REQUIRED); - } - } - // ok, name is sorted! - if (columnName != null) { - select.setUserData("name", columnName); - boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON) || column(columnName) != null; - if (select.has("collection")) { - JsonElement collectionJ = select.get("collection"); - if (!(collectionJ instanceof JsonBoolean)) { - error(path+".collection", collectionJ, "collection is not a boolean", IssueType.INVALID); - } else { - boolean collection = collectionJ.asJsonBoolean().asBoolean(); - if (!collection && isColl) { - isColl = false; - warning(path, select, "collection is false, but the path statement(s) might return multiple values for the column '"+columnName+"' some inputs"); - } - } - } - if (isColl && !arrays) { - warning(path, expression, "column appears to be a collection, but this is not allowed in this context"); - } - // ok collection is sorted - Set types = new HashSet<>(); - for (String type : td.getTypes()) { - types.add(simpleType(type)); - } + return true; + } + } + + private void checkColumn(String path, JsonObject column, TypeDetails t) { + if (!column.has("path")) { + error(path, column, "no path found", IssueType.INVALID); + } else { + JsonElement expression = column.get("path"); + if (!(expression instanceof JsonString)) { + error(path+".forEach", expression, "forEach is not a string", IssueType.INVALID); + } else { + String expr = expression.asString(); - JsonElement typeJ = select.get("type"); - if (typeJ != null) { - if (typeJ instanceof JsonString) { - String type = typeJ.asString(); - if (!td.hasType(type)) { - error(path+".type", typeJ, "The path expression does not return a value of the type '"+type, IssueType.VALUE); - } else { - types.clear(); - types.add(simpleType(type)); + List warnings = new ArrayList<>(); + TypeDetails td = null; + ExpressionNode node = null; + try { + node = fpe.parse(expr); + column.setUserData("path", node); + td = fpe.checkOnTypes(null, resourceName, t, node, warnings); + } catch (Exception e) { + error(path, expression, e.getMessage(), IssueType.INVALID); + } + if (td != null && node != null) { + for (String s : warnings) { + warning(path+".path", expression, s); + } + String columnName = null; + JsonElement aliasJ = column.get("alias"); + if (aliasJ != null) { + if (aliasJ instanceof JsonString) { + columnName = aliasJ.asString(); + if (!isValidName(columnName)) { + error(path+".name", aliasJ, "The name '"+columnName+"' is not valid", IssueType.VALUE); } } else { - error(path+".type", typeJ, "type must be a string", IssueType.INVALID); + error(path+".alias", aliasJ, "alias must be a string", IssueType.INVALID); } } - if (types.size() != 1) { - error(path, select, "Unable to determine a type (found "+td.describe()+")", IssueType.BUSINESSRULE); - } else { - String type = types.iterator().next(); - if (!isSimpleType(type) && !complexTypes) { - error(path, expression, "column is a complex type but this is not allowed in this context", IssueType.BUSINESSRULE); + if (columnName == null) { + List names = node.getDistalNames(); + if (names.size() == 1 && names.get(0) != null) { + columnName = names.get(0); + if (!isValidName(columnName)) { + error(path+".path", expression, "The name '"+columnName+"' found in the path expression is not a valid column name, so an alias is required", IssueType.INVARIANT); + } } else { - Column col = column(columnName); - if (col != null) { - if (!col.getType().equals(type)) { - error(path, expression, "Duplicate definition for "+columnName+" has different types ("+col.getType()+" vs "+type+")", IssueType.BUSINESSRULE); + error(path, column, "The path does not resolve to a name, so an alias is required", IssueType.REQUIRED); + } + } + // ok, name is sorted! + if (columnName != null) { + column.setUserData("name", columnName); + boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON) || column(columnName) != null; + if (column.has("collection")) { + JsonElement collectionJ = column.get("collection"); + if (!(collectionJ instanceof JsonBoolean)) { + error(path+".collection", collectionJ, "collection is not a boolean", IssueType.INVALID); + } else { + boolean collection = collectionJ.asJsonBoolean().asBoolean(); + if (!collection && isColl) { + isColl = false; + warning(path, column, "collection is false, but the path statement(s) might return multiple values for the column '"+columnName+"' some inputs"); } - if (col.isColl() != isColl) { - error(path, expression, "Duplicate definition for "+columnName+" has different status for collection ("+col.isColl()+" vs "+isColl+")", IssueType.BUSINESSRULE); + } + } + if (isColl) { + if (arrays == null) { + warning(path, expression, "column appears to be a collection. Collections are not supported in all Runners"); + } else if (!arrays) { + warning(path, expression, "column appears to be a collection, but this is not allowed in this context"); + } + } + // ok collection is sorted + Set types = new HashSet<>(); + for (String type : td.getTypes()) { + types.add(simpleType(type)); + } + + JsonElement typeJ = column.get("type"); + if (typeJ != null) { + if (typeJ instanceof JsonString) { + String type = typeJ.asString(); + if (!td.hasType(type)) { + error(path+".type", typeJ, "The path expression does not return a value of the type '"+type, IssueType.VALUE); + } else { + types.clear(); + types.add(simpleType(type)); } } else { - columns.add(new Column(columnName, isColl, type, kindForType(type))); + error(path+".type", typeJ, "type must be a string", IssueType.INVALID); + } + } + if (types.size() != 1) { + error(path, column, "Unable to determine a type (found "+td.describe()+")", IssueType.BUSINESSRULE); + } else { + String type = types.iterator().next(); + boolean ok = false; + if (!isSimpleType(type)) { + if (complexTypes) { + warning(path, expression, "Column is a complex type. This is not supported in some Runners"); + } else if (!complexTypes) { + error(path, expression, "Column is a complex type but this is not allowed in this context", IssueType.BUSINESSRULE); + } else { + ok = true; + } + } else { + ok = true; + } + if (ok) { + Column col = column(columnName); + if (col != null) { + if (!col.getType().equals(type)) { + error(path, expression, "Duplicate definition for "+columnName+" has different types ("+col.getType()+" vs "+type+")", IssueType.BUSINESSRULE); + } + if (col.isColl() != isColl) { + error(path, expression, "Duplicate definition for "+columnName+" has different status for collection ("+col.isColl()+" vs "+isColl+")", IssueType.BUSINESSRULE); + } + } else { + columns.add(new Column(columnName, isColl, type, kindForType(type))); + } } } } @@ -295,9 +380,10 @@ public class Validator { return type; } - private void checkForEach(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private TypeDetails checkForEach(String path, JsonObject focus, JsonElement expression, TypeDetails t) { if (!(expression instanceof JsonString)) { error(path+".forEach", expression, "forEach is not a string", IssueType.INVALID); + return null; } else { String expr = expression.asString(); @@ -312,28 +398,36 @@ public class Validator { } if (td != null) { for (String s : warnings) { - warning(path+".path", expression, s); - } - int i = 0; - if (checkAllObjects(path, focus, "select")) { - for (JsonObject select : focus.getJsonObjects("select")) { - checkSelect(path+".select["+i+"]", select, td); - i++; - } - if (i == 0) { - error(path, focus, "No select statements found", IssueType.REQUIRED); - } + warning(path+".forEach", expression, s); } } + return td; } } - private void checkForEachOrNull(String path, JsonObject focus, JsonElement expression, TypeDetails t) { - error(path+".forEachOrNull", expression, "forEachOrNull is not supported", IssueType.BUSINESSRULE); - } + private TypeDetails checkForEachOrNull(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + if (!(expression instanceof JsonString)) { + error(path+".forEachOrNull", expression, "forEachOrNull is not a string", IssueType.INVALID); + return null; + } else { + String expr = expression.asString(); - private void checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { - error(path+".union", focus.get("union"), "union is not supported", IssueType.BUSINESSRULE); + List warnings = new ArrayList<>(); + TypeDetails td = null; + try { + ExpressionNode n = fpe.parse(expr); + focus.setUserData("forEachOrNull", n); + td = fpe.checkOnTypes(null, resourceName, t, n, warnings); + } catch (Exception e) { + error(path, expression, e.getMessage(), IssueType.INVALID); + } + if (td != null) { + for (String s : warnings) { + warning(path+".forEachOrNull", expression, s); + } + } + return td; + } } private void checkConstant(String path, JsonObject constant) { @@ -481,27 +575,40 @@ public class Validator { issues.add(vm); } - public void dump() { - for (ValidationMessage vm : issues) { - System.out.println(vm.summary()); - } - + private void hint(String path, JsonElement e, String issue) { + ValidationMessage vm = new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, e.getStart().getLine(), e.getStart().getCol(), path, issue, IssueSeverity.INFORMATION); + issues.add(vm); } - public void check() { + public void dump() { + for (ValidationMessage vm : issues) { + System.out.println(vm.summary()); + } + + } + + public void check() { + if (!isOk()) { + throw new FHIRException("View Definition is not valid"); + } + + } + + public String getName() { + return name; + } + + public List getIssues() { + return issues; + } + + public boolean isOk() { boolean ok = true; for (ValidationMessage vm : issues) { if (vm.isError()) { ok = false; } } - if (!ok) { - throw new FHIRException("View Definition is not valid"); - } - - } - - public String getName() { - return name; + return ok; } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FHIRPathHostServices.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FHIRPathHostServices.java index 34edc5880..678d2b357 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FHIRPathHostServices.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FHIRPathHostServices.java @@ -100,4 +100,8 @@ public class FHIRPathHostServices implements FHIRPathEngine.IEvaluationContext { return structureMapUtilities.getWorker().fetchResource(ValueSet.class, url); } + @Override + public boolean paramIsType(String name, int index) { + return false; + } } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java index 028a21dac..b82d84db9 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java @@ -95,6 +95,10 @@ public class FHIRPathTests { return TestingUtilities.getSharedWorkerContext().fetchResource(ValueSet.class, url); } + @Override + public boolean paramIsType(String name, int index) { + return false; + } } private static FHIRPathEngine fp; diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java index bd299d30f..d089a373d 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java @@ -420,6 +420,10 @@ public class SnapShotGenerationTests { throw new Error("Not implemented yet"); } + @Override + public boolean paramIsType(String name, int index) { + return false; + } } private static FHIRPathEngine fp; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 306ac6bd1..d350965df 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -232,7 +232,7 @@ Type_Specific_Checks_DT_URL_Resolve = URL value ''{0}'' does not resolve Type_Specific_Checks_DT_UUID_Strat = UUIDs must start with urn:uuid: Type_Specific_Checks_DT_UUID_Valid = UUIDs must be valid and lowercase ({0}) Validation_BUNDLE_Message = The first entry in a message must be a MessageHeader -Validation_VAL_Content_Unknown = Unrecognised Content {0} +Validation_VAL_Content_Unknown = Unrecognized Content {0} Validation_VAL_NoType = Unknown type {0} Validation_VAL_Profile_MatchMultiple = Profile {0}, Element matches more than one slice - {1}, {2} ## for the next 4 messages, the available parameters are: 0: profile url, 1: ed.path, 2: ed.id, 3: ed.sliceName, 4: ed.label, 5: element.path, 6: ed.min and optionally 7: actual count @@ -305,7 +305,7 @@ No_reference_resolving_discriminator__from_ = No reference resolving discriminat Unable_to_resolve_element__in_profile_ = Unable to resolve element {0} in profile {1} Unable_to_resolve_profile_ = Unable to resolve profile {0} Resource_resolution_services_not_provided = Resource resolution services not provided -Unrecognised_extension_context_ = Unrecognised extension context {0} +Unrecognised_extension_context_ = Unrecognized extension context {0} Unable_to_locate_the_profile__in_order_to_validate_against_it = Unable to locate the profile ''{0}'' in order to validate against it Reference__refers_to_a__not_a_ValueSet = Reference {0} refers to a {1} not a ValueSet Not_done_yet_ValidatorHostServicesconformsToProfile_when_item_is_not_an_element = Not done yet (ValidatorHostServices.conformsToProfile), when item is not an element @@ -394,9 +394,9 @@ Does_not_match_slice_ = Does not match slice ''{0}'' (discriminator: {1}) Profile__does_not_match_for__because_of_the_following_profile_issues__ = Profile {0} does not match for {1} because of the following profile issues: {2} This_element_does_not_match_any_known_slice_ = This element does not match any known slice {0} defined_in_the_profile = Defined in the profile -This_does_not_appear_to_be_a_FHIR_resource_unknown_name_ = This content cannot be parsed (unknown or unrecognised XML root element name ''{0}'') +This_does_not_appear_to_be_a_FHIR_resource_unknown_name_ = This content cannot be parsed (unknown or unrecognized resource name ''{0}'') This_cannot_be_parsed_as_a_FHIR_object_no_name = This content cannot be parsed (no name) -This_does_not_appear_to_be_a_FHIR_resource_unknown_namespacename_ = This content cannot be parsed (unknown or unrecognised XML Root element namespace/name ''{0}::{1}'') +This_does_not_appear_to_be_a_FHIR_resource_unknown_namespacename_ = This content cannot be parsed (unknown or unrecognized XML Root element namespace/name ''{0}::{1}'') This__cannot_be_parsed_as_a_FHIR_object_no_namespace = This ''{0}'' cannot be parsed (no namespace on the XML Root element) Unable_to_find_resourceType_property = Unable to find resourceType property Error_parsing_JSON_the_primitive_value_must_be_a_string = Error parsing JSON: the primitive value must be a string @@ -427,7 +427,7 @@ Unknown_resource_type_missing_rdfstype = Unknown resource type (missing rdfs:typ reference_to__cannot_be_resolved = reference to {0} cannot be resolved This_property_must_be_a_URI_or_bnode_not_ = This property must be a URI or bnode, not {0} This_property_must_be_a_Literal_not_ = This property must be a Literal, not {0} -Unrecognised_predicate_ = Unrecognised predicate ''{0}'' +Unrecognised_predicate_ = Unrecognized predicate ''{0}'' Error_parsing_Turtle_ = Error parsing Turtle: {0} Unexpected_datatype_for_rdfstype = Unexpected datatype for rdfs:type Attempt_to_replace_element_name_for_a_nonchoice_type=Attempt to replace element name for a non-choice type diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java index 2d674e43d..a21b0971c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java @@ -337,6 +337,11 @@ public class ValidatorCli { res.add("5.0"); res.add("-ig"); res.add("hl7.cda.uv.core#2.1.0-draft1"); + } else if (a.equals("-view-definition")) { + res.add("-version"); + res.add("5.0"); + res.add("-ig"); + res.add("hl7.fhir.uv.sql-on-fhir#current"); } else { res.add(a); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index c30f61bf9..bc3e83f69 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -160,6 +160,7 @@ import org.hl7.fhir.r5.utils.FHIRPathUtilityClasses.TypedElementDefinition; import org.hl7.fhir.r5.utils.ResourceUtilities; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.XVerExtensionManager; +import org.hl7.fhir.r5.utils.sql.Validator; import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; @@ -429,6 +430,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return context.fetchResource(ValueSet.class, url); } + @Override + public boolean paramIsType(String name, int index) { + return false; + } + } private FHIRPathEngine fpe; @@ -5379,6 +5385,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return new StructureMapValidator(this, fpe, profileUtilities).validateStructureMap(errors, element, stack) && ok; } else if (element.getType().equals("ValueSet")) { return new ValueSetValidator(this).validateValueSet(errors, element, stack) && ok; + } else if ("http://hl7.org/fhir/uv/sql-on-fhir/StructureDefinition/ViewDefinition".equals(element.getProperty().getStructure().getUrl())) { + if (element.getNativeObject() != null && element.getNativeObject() instanceof JsonObject) { + JsonObject json = (JsonObject) element.getNativeObject(); + Validator sqlv = new Validator(context, fpe, new ArrayList<>(), null, null, null); + sqlv.checkViewDefinition(stack.getLiteralPath(), json); + errors.addAll(sqlv.getIssues()); + ok = sqlv.isOk() && ok; + } + return ok; } else { return ok; } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java index 48ee30723..8ba86322d 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java @@ -397,6 +397,10 @@ public class SnapShotGenerationXTests { throw new Error("Not implemented yet"); } + @Override + public boolean paramIsType(String name, int index) { + return false; + } } private static FHIRPathEngine fp; @@ -577,4 +581,6 @@ public class SnapShotGenerationXTests { } return sd; } + + } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java index 9e7c4c7cf..d7429594c 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java @@ -804,4 +804,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe } } + + @Override + public boolean paramIsType(String name, int index) { + return false; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3a889c02e..270349aca 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 32.0.1-jre 6.4.1 - 1.4.10 + 1.4.11-SNAPSHOT 2.15.2 5.9.2 1.8.2