Finish CDS hooks extension validation

This commit is contained in:
Grahame Grieve 2022-10-29 19:18:19 +11:00
parent ddf769851b
commit 5116536617
2 changed files with 63 additions and 31 deletions

View File

@ -66,6 +66,7 @@ import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.json.JsonTrackingParser; import org.hl7.fhir.utilities.json.JsonTrackingParser;
import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData;
import org.hl7.fhir.utilities.json.JsonUtilities;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.xhtml.XhtmlParser; import org.hl7.fhir.utilities.xhtml.XhtmlParser;
@ -227,15 +228,15 @@ public class JsonParser extends ParserBase {
if (property.isJsonPrimitiveChoice()) { if (property.isJsonPrimitiveChoice()) {
if (object.has(property.getJsonName())) { if (object.has(property.getJsonName())) {
JsonElement je = object.get(property.getJsonName()); JsonElement je = object.get(property.getJsonName());
String type = getTypeFromJsonType(je);
if (processed != null) processed.add(property.getJsonName()); if (processed != null) processed.add(property.getJsonName());
String type = getTypeFromJsonType(je);
if (type == null) { if (type == null) {
logError(line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, property.getName(), property.typeSummary()), IssueSeverity.ERROR); logError(line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(je), property.getName(), property.typeSummary()), IssueSeverity.ERROR);
} else if (property.hasType(type)) { } else if (property.hasType(type)) {
Property np = new Property(property.getContext(), property.getDefinition(), property.getStructure(), property.getUtils(), type); Property np = new Property(property.getContext(), property.getDefinition(), property.getStructure(), property.getUtils(), type);
parseChildPrimitive(object, context, processed, np, path, property.getName()); parseChildPrimitive(object, context, processed, np, path, property.getName());
} else { } else {
logError(line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, property.getName(), type, property.typeSummary()), IssueSeverity.ERROR); logError(line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(je), property.getName(), type, property.typeSummary()), IssueSeverity.ERROR);
} }
} }
} else { } else {
@ -312,7 +313,7 @@ public class JsonParser extends ParserBase {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE, propNames(properties), propK.typeSummary()), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE, propNames(properties), propK.typeSummary()), IssueSeverity.ERROR);
} else if (propV.isList()) { } else if (propV.isList()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST, propV.getName()), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST, propV.getName()), IssueSeverity.ERROR);
} else if (propV.isChoice()) { } else if (propV.isChoice() && propV.getName().endsWith("[x]")) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE, propV.getName()), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE, propV.getName()), IssueSeverity.ERROR);
} else if (!(e instanceof JsonObject)) { } else if (!(e instanceof JsonObject)) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR);
@ -334,15 +335,32 @@ public class JsonParser extends ParserBase {
n.getChildren().add(nKey); n.getChildren().add(nKey);
nKey.setValue(pv.getKey()); nKey.setValue(pv.getKey());
// handle the value
String npathV = npathArr+"."+propV.getName(); boolean ok = true;
String fpathV = fpathArr+"."+propV.getName(); Property pvl = propV;
if (propV.isPrimitive(propV.getType(null))) { if (propV.isJsonPrimitiveChoice()) {
parseChildPrimitiveInstance(n, propV, propV.getName(), npathV, fpathV, pv.getValue(), null); ok = false;
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) { String type = getTypeFromJsonType(pv.getValue());
parseChildComplexInstance(npathV, fpathV, n, propV, propV.getName(), pv.getValue()); if (type == null) {
} else { logError(line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(pv.getValue()), propV.getName(), propV.typeSummary()), IssueSeverity.ERROR);
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR); } else if (propV.hasType(type)) {
pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type);
ok = true;
} else {
logError(line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(pv.getValue()), propV.getName(), type, propV.typeSummary()), IssueSeverity.ERROR);
}
}
if (ok) {
// handle the value
String npathV = npathArr+"."+pvl.getName();
String fpathV = fpathArr+"."+pvl.getName();
if (propV.isPrimitive(pvl.getType(null))) {
parseChildPrimitiveInstance(n, pvl, pvl.getName(), npathV, fpathV, pv.getValue(), null);
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue());
} else {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
}
} }
i++; i++;
} }
@ -350,7 +368,7 @@ public class JsonParser extends ParserBase {
} }
} else { } else {
if (property.isList()) { if (property.isList()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describeType(e), name, path), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(e), name, path), IssueSeverity.ERROR);
} }
parseChildComplexInstance(npath, fpath, element, property, name, e); parseChildComplexInstance(npath, fpath, element, property, name, e);
} }
@ -364,18 +382,6 @@ public class JsonParser extends ParserBase {
return b.toString(); return b.toString();
} }
private String describeType(JsonElement e) {
if (e.isJsonArray())
return "an Array";
if (e.isJsonObject())
return "an Object";
if (e.isJsonPrimitive())
return "a primitive property";
if (e.isJsonNull())
return "a Null";
return null;
}
private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e) throws FHIRException { private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e) throws FHIRException {
if (property.hasTypeSpecifier()) { if (property.hasTypeSpecifier()) {
FHIRPathEngine fpe = new FHIRPathEngine(context); FHIRPathEngine fpe = new FHIRPathEngine(context);
@ -433,15 +439,41 @@ public class JsonParser extends ParserBase {
private String describe(JsonElement e) { private String describe(JsonElement e) {
if (e instanceof JsonArray) { if (e instanceof JsonArray) {
return "an array"; return "an Array";
} }
if (e instanceof JsonObject) { if (e instanceof JsonObject) {
return "an object"; return "an Object";
}
if (e instanceof JsonNull) {
return "a Null";
}
if (e instanceof JsonPrimitive) {
return "a Primitive property";
}
return null;
}
private String describeType(JsonElement e) {
if (e instanceof JsonArray) {
return "array";
}
if (e instanceof JsonObject) {
return "object";
} }
if (e instanceof JsonNull) { if (e instanceof JsonNull) {
return "null"; return "null";
} }
return "a primitive property"; if (e instanceof JsonPrimitive) {
JsonPrimitive p = (JsonPrimitive) e;
if (p.isString()) {
return "string";
} else if (p.isBoolean()) {
return "boolean";
} else if (p.isNumber()) {
return "number";
}
}
return "??";
} }
private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException { private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException {

View File

@ -753,5 +753,5 @@ TYPE_SPECIFIER_NM_ILLEGAL_TYPE = No Type specifier matched, and the underlying t
TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract
ELEMENT_CANNOT_BE_NULL = The element is not allowed to be 'null' ELEMENT_CANNOT_BE_NULL = The element is not allowed to be 'null'
MULTIPLE_LOGICAL_MODELS_PLURAL={0} Logical Models found in supplied profiles, so unable to parse logical model (can only be one, found {1}) MULTIPLE_LOGICAL_MODELS_PLURAL={0} Logical Models found in supplied profiles, so unable to parse logical model (can only be one, found {1})
UNRECOGNISED_PROPERTY_TYPE = Invalid JSON type for the element {0}; valid types = {1} UNRECOGNISED_PROPERTY_TYPE = Invalid JSON type {0} for the element {1}; valid types = {2}
UNRECOGNISED_PROPERTY_TYPE_WRONG = Invalid type {1} for the element {0}; valid types = {2} UNRECOGNISED_PROPERTY_TYPE_WRONG = Invalid type {2} for the element {1}; valid types = {3}, JSON type = {0}