commit
682352e24a
|
@ -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<String, String> getAllCIPackages() throws IOException {
|
||||
System.out.println("Fetch https://build.fhir.org/ig/qas.json");
|
||||
Map<String, String> 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;
|
||||
|
|
|
@ -308,4 +308,9 @@ public class ComparisonRenderer implements IEvaluationContext {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean paramIsType(String name, int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -193,6 +193,7 @@ public class JsonParser extends ParserBase {
|
|||
}
|
||||
|
||||
private void checkObject(List<ValidationMessage> errors, JsonObject object, Element b, String path) {
|
||||
b.setNativeObject(object);
|
||||
checkComments(errors, object, b, path);
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
if (object.getProperties().size() == 0) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -302,7 +302,7 @@ public class XmlParser extends ParserBase {
|
|||
|
||||
public Element parse(List<ValidationMessage> 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());
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1265,7 +1265,9 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
|
||||
public boolean validateCodeInConceptList(String code, CodeSystem def, List<ConceptDefinitionComponent> 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;
|
||||
|
|
|
@ -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<ElementDefinition> elementDependencies, ExpressionNode container) throws PathEngineException, DefinitionException {
|
||||
List<TypeDetails> paramTypes = new ArrayList<TypeDetails>();
|
||||
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<List<Base>> params = new ArrayList<List<Base>>();
|
||||
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<Base> 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);
|
||||
}
|
||||
|
|
|
@ -853,4 +853,8 @@ public class LiquidEngine implements IEvaluationContext {
|
|||
return replaced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean paramIsType(String name, int index) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -111,7 +111,11 @@ public class Runner implements IEvaluationContext {
|
|||
}
|
||||
if (ok) {
|
||||
List<List<Cell>> rows = new ArrayList<>();
|
||||
generateCells(b, vd, rows);
|
||||
rows.add(new ArrayList<Cell>());
|
||||
|
||||
for (JsonObject select : vd.getJsonObjects("select")) {
|
||||
executeSelect(select, b, rows);
|
||||
}
|
||||
for (List<Cell> 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<List<Cell>> 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<List<Cell>> 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<List<Cell>> rows) {
|
||||
List<Base> 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<List<Cell>> rows) {
|
||||
ExpressionNode n = (ExpressionNode) focus.getUserData("forEach");
|
||||
List<Base> bl2 = fpe.evaluate(b, n);
|
||||
// } else if (select.has("union")) {
|
||||
// focus.addAll(executeUnion(select, b));
|
||||
|
||||
List<List<Cell>> tempRows = new ArrayList<>();
|
||||
tempRows.addAll(rows);
|
||||
rows.clear();
|
||||
for (Base b2 : bl2) {
|
||||
List<List<Cell>> rowsToAdd = cloneRows(tempRows);
|
||||
for (JsonObject select : focus.getJsonObjects("select")) {
|
||||
executeSelect(select, b2, rowsToAdd);
|
||||
|
||||
for (Base f : focus) {
|
||||
List<List<Cell>> 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<Base> executeUnion(JsonObject focus, Base b, List<List<Cell>> rows) {
|
||||
throw new FHIRException("union is not supported");
|
||||
}
|
||||
|
||||
private List<List<Cell>> cloneRows(List<List<Cell>> rows) {
|
||||
List<List<Cell>> list = new ArrayList<>();
|
||||
for (List<Cell> row : rows) {
|
||||
|
@ -176,30 +179,38 @@ public class Runner implements IEvaluationContext {
|
|||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void executeForEachOrNull(JsonObject focus, Base b, List<List<Cell>> rows) {
|
||||
throw new FHIRException("forEachOrNull is not supported");
|
||||
|
||||
private List<Base> executeForEach(JsonObject focus, Base b) {
|
||||
ExpressionNode n = (ExpressionNode) focus.getUserData("forEach");
|
||||
List<Base> result = new ArrayList<>();
|
||||
result.addAll(fpe.evaluate(b, n));
|
||||
return result;
|
||||
}
|
||||
|
||||
private void executeUnion(JsonObject focus, Base b, List<List<Cell>> rows) {
|
||||
throw new FHIRException("union is not supported");
|
||||
private List<Base> executeForEachOrNull(JsonObject focus, Base b) {
|
||||
ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull");
|
||||
List<Base> 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<List<Cell>> rows) {
|
||||
ExpressionNode n = (ExpressionNode) select.getUserData("path");
|
||||
List<Base> bl2 = fpe.evaluate(b, n);
|
||||
String name = select.getUserString("name");
|
||||
if (!bl2.isEmpty()) {
|
||||
if (rows.isEmpty()) {
|
||||
rows.add(new ArrayList<Cell>());
|
||||
}
|
||||
for (List<Cell> 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<List<Cell>> rows) {
|
||||
ExpressionNode n = (ExpressionNode) column.getUserData("path");
|
||||
List<Base> bl2 = new ArrayList<>();
|
||||
if (b != null) {
|
||||
bl2.addAll(fpe.evaluate(b, n));
|
||||
}
|
||||
String name = column.getUserString("name");
|
||||
for (List<Cell> 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<Cell> 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> base = new ArrayList<Base>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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<String> prohibitedNames = new ArrayList<String>();
|
||||
private List<ValidationMessage> issues = new ArrayList<ValidationMessage>();
|
||||
private boolean arrays;
|
||||
private boolean complexTypes;
|
||||
private boolean needsName;
|
||||
private Boolean arrays;
|
||||
private Boolean complexTypes;
|
||||
private Boolean needsName;
|
||||
|
||||
private String resourceName;
|
||||
private List<Column> columns = new ArrayList<Column>();
|
||||
private String name;
|
||||
|
||||
protected Validator(IWorkerContext context, FHIRPathEngine fpe, List<String> prohibitedNames, boolean arrays, boolean complexTypes, boolean needsName) {
|
||||
public Validator(IWorkerContext context, FHIRPathEngine fpe, List<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<ValidationMessage> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -804,4 +804,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean paramIsType(String name, int index) {
|
||||
return false;
|
||||
}
|
||||
}
|
2
pom.xml
2
pom.xml
|
@ -20,7 +20,7 @@
|
|||
<properties>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.4.10</validator_test_case_version>
|
||||
<validator_test_case_version>1.4.11-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.15.2</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue